Repository: refinedmods/refinedstorage Branch: develop Commit: 60ce906c1699 Files: 2808 Total size: 3.6 MB Directory structure: gitextract_ju5e0fkm/ ├── .github/ │ ├── CONTRIBUTING.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ └── config.yml │ ├── SUPPORT.md │ └── workflows/ │ ├── build.yml │ ├── draft-release.yml │ ├── issue-for-unsupported-version.yml │ ├── publish-release.yml │ ├── resolved-issue-locking.yml │ ├── validate-branch-name.yml │ ├── validate-changelog.yml │ └── validate-commit-messages.yml ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── build.gradle ├── config/ │ └── checkstyle/ │ └── checkstyle.xml ├── docs/ │ ├── nav.json │ ├── pages/ │ │ ├── advanced-usage/ │ │ │ ├── commands.adoc │ │ │ ├── index.adoc │ │ │ ├── profiling.adoc │ │ │ ├── resource-packs.adoc │ │ │ ├── translating-refined-storage.adoc │ │ │ ├── using-development-builds.adoc │ │ │ └── using-the-api.adoc │ │ ├── autocrafting/ │ │ │ ├── autocrafting-with-filled-buckets.adoc │ │ │ ├── crafter-manager.adoc │ │ │ ├── crafter.adoc │ │ │ ├── crafting-monitor.adoc │ │ │ ├── fluid-autocrafting.adoc │ │ │ ├── getting-started-with-autocrafting.adoc │ │ │ ├── index.adoc │ │ │ ├── keeping-fluids-in-stock.adoc │ │ │ ├── keeping-items-in-stock.adoc │ │ │ ├── locking-and-unlocking.adoc │ │ │ ├── pattern-grid.adoc │ │ │ ├── pattern.adoc │ │ │ ├── processing-pattern-encoder.adoc │ │ │ └── processing-recipes.adoc │ │ ├── faq.adoc │ │ ├── getting-started.adoc │ │ ├── how-to-install.adoc │ │ ├── index.adoc │ │ ├── index.html │ │ ├── input-and-output/ │ │ │ ├── constructor.adoc │ │ │ ├── destructor.adoc │ │ │ ├── disk-manipulator.adoc │ │ │ ├── exporter.adoc │ │ │ ├── fluid-interface.adoc │ │ │ ├── getting-items-in-and-out.adoc │ │ │ ├── importer.adoc │ │ │ ├── index.adoc │ │ │ ├── interface.adoc │ │ │ ├── reader.adoc │ │ │ └── writer.adoc │ │ ├── need-help.adoc │ │ ├── need-help.html │ │ ├── networking/ │ │ │ ├── cable.adoc │ │ │ ├── controller.adoc │ │ │ ├── creative-controller.adoc │ │ │ ├── detector.adoc │ │ │ ├── index.adoc │ │ │ └── relay.adoc │ │ ├── news/ │ │ │ ├── 20210518-announcing-refined-storage-2.adoc │ │ │ ├── 20220704-a-big-milestone-for-refined-storage-2.adoc │ │ │ ├── 20230707-a-week-of-modding.adoc │ │ │ ├── 20230819-refined-storage-2-milestone-2-completed.adoc │ │ │ ├── 20240319-refined-storage-2-status-update-march.adoc │ │ │ ├── 20240628-refined-storage-2-milestone-3-completed.adoc │ │ │ ├── index.adoc │ │ │ └── index.html │ │ ├── opencomputers-api.adoc │ │ ├── release-notes.adoc │ │ ├── release-notes.html │ │ ├── security/ │ │ │ ├── index.adoc │ │ │ ├── security-card.adoc │ │ │ └── security-manager.adoc │ │ ├── storage/ │ │ │ ├── 1024k-fluid-storage-block.adoc │ │ │ ├── 1024k-fluid-storage-disk.adoc │ │ │ ├── 1024k-fluid-storage-part.adoc │ │ │ ├── 16k-storage-block.adoc │ │ │ ├── 16k-storage-disk.adoc │ │ │ ├── 16k-storage-part.adoc │ │ │ ├── 1k-storage-block.adoc │ │ │ ├── 1k-storage-disk.adoc │ │ │ ├── 1k-storage-part.adoc │ │ │ ├── 256k-fluid-storage-block.adoc │ │ │ ├── 256k-fluid-storage-disk.adoc │ │ │ ├── 256k-fluid-storage-part.adoc │ │ │ ├── 4096k-fluid-storage-block.adoc │ │ │ ├── 4096k-fluid-storage-disk.adoc │ │ │ ├── 4096k-fluid-storage-part.adoc │ │ │ ├── 4k-storage-block.adoc │ │ │ ├── 4k-storage-disk.adoc │ │ │ ├── 4k-storage-part.adoc │ │ │ ├── 64k-fluid-storage-block.adoc │ │ │ ├── 64k-fluid-storage-disk.adoc │ │ │ ├── 64k-fluid-storage-part.adoc │ │ │ ├── 64k-storage-block.adoc │ │ │ ├── 64k-storage-disk.adoc │ │ │ ├── 64k-storage-part.adoc │ │ │ ├── creative-fluid-storage-block.adoc │ │ │ ├── creative-fluid-storage-disk.adoc │ │ │ ├── creative-storage-block.adoc │ │ │ ├── creative-storage-disk.adoc │ │ │ ├── disk-drive.adoc │ │ │ ├── external-storage.adoc │ │ │ ├── index.adoc │ │ │ ├── storage-housing.adoc │ │ │ ├── storing-externally.adoc │ │ │ └── storing-fluids.adoc │ │ ├── upgrades/ │ │ │ ├── crafting-upgrade.adoc │ │ │ ├── fortune-upgrade.adoc │ │ │ ├── index.adoc │ │ │ ├── interdimensional-upgrade.adoc │ │ │ ├── range-upgrade.adoc │ │ │ ├── regulator-upgrade.adoc │ │ │ ├── silk-touch-upgrade.adoc │ │ │ ├── speed-upgrade.adoc │ │ │ ├── stack-upgrade.adoc │ │ │ └── upgrade.adoc │ │ ├── utility/ │ │ │ ├── advanced-processor.adoc │ │ │ ├── basic-processor.adoc │ │ │ ├── block-of-quartz-enriched-iron.adoc │ │ │ ├── construction-core.adoc │ │ │ ├── cover.adoc │ │ │ ├── cut-silicon.adoc │ │ │ ├── cutting-tool.adoc │ │ │ ├── destruction-core.adoc │ │ │ ├── filter.adoc │ │ │ ├── hollow-cover.adoc │ │ │ ├── improved-processor.adoc │ │ │ ├── index.adoc │ │ │ ├── machine-casing.adoc │ │ │ ├── processor-binding.adoc │ │ │ ├── quartz-enriched-iron.adoc │ │ │ ├── raw-advanced-processor.adoc │ │ │ ├── raw-basic-processor.adoc │ │ │ ├── raw-improved-processor.adoc │ │ │ ├── silicon.adoc │ │ │ ├── solderer.adoc │ │ │ └── wrench.adoc │ │ ├── viewing-resources/ │ │ │ ├── crafting-grid.adoc │ │ │ ├── fluid-grid.adoc │ │ │ ├── grid.adoc │ │ │ ├── how-to-view-resources.adoc │ │ │ ├── index.adoc │ │ │ ├── portable-grid.adoc │ │ │ └── storage-monitor.adoc │ │ └── wireless-networking/ │ │ ├── creative-wireless-crafting-monitor.adoc │ │ ├── creative-wireless-fluid-grid.adoc │ │ ├── creative-wireless-grid.adoc │ │ ├── index.adoc │ │ ├── network-card.adoc │ │ ├── network-receiver.adoc │ │ ├── network-transmitter.adoc │ │ ├── networks-over-long-distances.adoc │ │ ├── wireless-crafting-grid.adoc │ │ ├── wireless-crafting-monitor.adoc │ │ ├── wireless-fluid-grid.adoc │ │ ├── wireless-grid.adoc │ │ └── wireless-transmitter.adoc │ └── partials/ │ ├── fluid-storage-block.adoc │ ├── fluid-storage-disk.adoc │ ├── processor.adoc │ ├── recoloring.adoc │ ├── search-box.adoc │ ├── storage-block.adoc │ └── storage-disk.adoc ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── images/ │ └── description.md ├── src/ │ ├── generated/ │ │ └── resources/ │ │ ├── .cache/ │ │ │ ├── 59eb3dbb5f86130e09b3c62d89b9525ee01cf52d │ │ │ ├── 9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e │ │ │ ├── c52895b732924e707cb6e5ddd1c6b6962039449c │ │ │ ├── cb654f100e416ac39358630d6623170b9bfdc5d2 │ │ │ ├── f481442ce31db2c3b3dabb5b6d85f9a78568164e │ │ │ └── fd27170b6bf91459ed2598d25721edfeafc82e0a │ │ ├── assets/ │ │ │ └── refinedstorage/ │ │ │ ├── blockstates/ │ │ │ │ ├── black_controller.json │ │ │ │ ├── black_crafter.json │ │ │ │ ├── black_crafter_manager.json │ │ │ │ ├── black_crafting_grid.json │ │ │ │ ├── black_crafting_monitor.json │ │ │ │ ├── black_creative_controller.json │ │ │ │ ├── black_detector.json │ │ │ │ ├── black_disk_manipulator.json │ │ │ │ ├── black_fluid_grid.json │ │ │ │ ├── black_grid.json │ │ │ │ ├── black_network_receiver.json │ │ │ │ ├── black_network_transmitter.json │ │ │ │ ├── black_pattern_grid.json │ │ │ │ ├── black_relay.json │ │ │ │ ├── black_security_manager.json │ │ │ │ ├── black_wireless_transmitter.json │ │ │ │ ├── blue_controller.json │ │ │ │ ├── blue_crafter.json │ │ │ │ ├── blue_crafter_manager.json │ │ │ │ ├── blue_crafting_grid.json │ │ │ │ ├── blue_crafting_monitor.json │ │ │ │ ├── blue_creative_controller.json │ │ │ │ ├── blue_detector.json │ │ │ │ ├── blue_disk_manipulator.json │ │ │ │ ├── blue_fluid_grid.json │ │ │ │ ├── blue_grid.json │ │ │ │ ├── blue_network_receiver.json │ │ │ │ ├── blue_network_transmitter.json │ │ │ │ ├── blue_pattern_grid.json │ │ │ │ ├── blue_relay.json │ │ │ │ ├── blue_security_manager.json │ │ │ │ ├── blue_wireless_transmitter.json │ │ │ │ ├── brown_controller.json │ │ │ │ ├── brown_crafter.json │ │ │ │ ├── brown_crafter_manager.json │ │ │ │ ├── brown_crafting_grid.json │ │ │ │ ├── brown_crafting_monitor.json │ │ │ │ ├── brown_creative_controller.json │ │ │ │ ├── brown_detector.json │ │ │ │ ├── brown_disk_manipulator.json │ │ │ │ ├── brown_fluid_grid.json │ │ │ │ ├── brown_grid.json │ │ │ │ ├── brown_network_receiver.json │ │ │ │ ├── brown_network_transmitter.json │ │ │ │ ├── brown_pattern_grid.json │ │ │ │ ├── brown_relay.json │ │ │ │ ├── brown_security_manager.json │ │ │ │ ├── brown_wireless_transmitter.json │ │ │ │ ├── controller.json │ │ │ │ ├── crafter.json │ │ │ │ ├── crafter_manager.json │ │ │ │ ├── crafting_grid.json │ │ │ │ ├── crafting_monitor.json │ │ │ │ ├── creative_controller.json │ │ │ │ ├── cyan_controller.json │ │ │ │ ├── cyan_crafter.json │ │ │ │ ├── cyan_crafter_manager.json │ │ │ │ ├── cyan_crafting_grid.json │ │ │ │ ├── cyan_crafting_monitor.json │ │ │ │ ├── cyan_creative_controller.json │ │ │ │ ├── cyan_detector.json │ │ │ │ ├── cyan_disk_manipulator.json │ │ │ │ ├── cyan_fluid_grid.json │ │ │ │ ├── cyan_grid.json │ │ │ │ ├── cyan_network_receiver.json │ │ │ │ ├── cyan_network_transmitter.json │ │ │ │ ├── cyan_pattern_grid.json │ │ │ │ ├── cyan_relay.json │ │ │ │ ├── cyan_security_manager.json │ │ │ │ ├── cyan_wireless_transmitter.json │ │ │ │ ├── detector.json │ │ │ │ ├── disk_manipulator.json │ │ │ │ ├── fluid_grid.json │ │ │ │ ├── gray_controller.json │ │ │ │ ├── gray_crafter.json │ │ │ │ ├── gray_crafter_manager.json │ │ │ │ ├── gray_crafting_grid.json │ │ │ │ ├── gray_crafting_monitor.json │ │ │ │ ├── gray_creative_controller.json │ │ │ │ ├── gray_detector.json │ │ │ │ ├── gray_disk_manipulator.json │ │ │ │ ├── gray_fluid_grid.json │ │ │ │ ├── gray_grid.json │ │ │ │ ├── gray_network_receiver.json │ │ │ │ ├── gray_network_transmitter.json │ │ │ │ ├── gray_pattern_grid.json │ │ │ │ ├── gray_relay.json │ │ │ │ ├── gray_security_manager.json │ │ │ │ ├── gray_wireless_transmitter.json │ │ │ │ ├── green_controller.json │ │ │ │ ├── green_crafter.json │ │ │ │ ├── green_crafter_manager.json │ │ │ │ ├── green_crafting_grid.json │ │ │ │ ├── green_crafting_monitor.json │ │ │ │ ├── green_creative_controller.json │ │ │ │ ├── green_detector.json │ │ │ │ ├── green_disk_manipulator.json │ │ │ │ ├── green_fluid_grid.json │ │ │ │ ├── green_grid.json │ │ │ │ ├── green_network_receiver.json │ │ │ │ ├── green_network_transmitter.json │ │ │ │ ├── green_pattern_grid.json │ │ │ │ ├── green_relay.json │ │ │ │ ├── green_security_manager.json │ │ │ │ ├── green_wireless_transmitter.json │ │ │ │ ├── grid.json │ │ │ │ ├── light_gray_controller.json │ │ │ │ ├── light_gray_crafter.json │ │ │ │ ├── light_gray_crafter_manager.json │ │ │ │ ├── light_gray_crafting_grid.json │ │ │ │ ├── light_gray_crafting_monitor.json │ │ │ │ ├── light_gray_creative_controller.json │ │ │ │ ├── light_gray_detector.json │ │ │ │ ├── light_gray_disk_manipulator.json │ │ │ │ ├── light_gray_fluid_grid.json │ │ │ │ ├── light_gray_grid.json │ │ │ │ ├── light_gray_network_receiver.json │ │ │ │ ├── light_gray_network_transmitter.json │ │ │ │ ├── light_gray_pattern_grid.json │ │ │ │ ├── light_gray_relay.json │ │ │ │ ├── light_gray_security_manager.json │ │ │ │ ├── light_gray_wireless_transmitter.json │ │ │ │ ├── lime_controller.json │ │ │ │ ├── lime_crafter.json │ │ │ │ ├── lime_crafter_manager.json │ │ │ │ ├── lime_crafting_grid.json │ │ │ │ ├── lime_crafting_monitor.json │ │ │ │ ├── lime_creative_controller.json │ │ │ │ ├── lime_detector.json │ │ │ │ ├── lime_disk_manipulator.json │ │ │ │ ├── lime_fluid_grid.json │ │ │ │ ├── lime_grid.json │ │ │ │ ├── lime_network_receiver.json │ │ │ │ ├── lime_network_transmitter.json │ │ │ │ ├── lime_pattern_grid.json │ │ │ │ ├── lime_relay.json │ │ │ │ ├── lime_security_manager.json │ │ │ │ ├── lime_wireless_transmitter.json │ │ │ │ ├── magenta_controller.json │ │ │ │ ├── magenta_crafter.json │ │ │ │ ├── magenta_crafter_manager.json │ │ │ │ ├── magenta_crafting_grid.json │ │ │ │ ├── magenta_crafting_monitor.json │ │ │ │ ├── magenta_creative_controller.json │ │ │ │ ├── magenta_detector.json │ │ │ │ ├── magenta_disk_manipulator.json │ │ │ │ ├── magenta_fluid_grid.json │ │ │ │ ├── magenta_grid.json │ │ │ │ ├── magenta_network_receiver.json │ │ │ │ ├── magenta_network_transmitter.json │ │ │ │ ├── magenta_pattern_grid.json │ │ │ │ ├── magenta_relay.json │ │ │ │ ├── magenta_security_manager.json │ │ │ │ ├── magenta_wireless_transmitter.json │ │ │ │ ├── network_receiver.json │ │ │ │ ├── network_transmitter.json │ │ │ │ ├── orange_controller.json │ │ │ │ ├── orange_crafter.json │ │ │ │ ├── orange_crafter_manager.json │ │ │ │ ├── orange_crafting_grid.json │ │ │ │ ├── orange_crafting_monitor.json │ │ │ │ ├── orange_creative_controller.json │ │ │ │ ├── orange_detector.json │ │ │ │ ├── orange_disk_manipulator.json │ │ │ │ ├── orange_fluid_grid.json │ │ │ │ ├── orange_grid.json │ │ │ │ ├── orange_network_receiver.json │ │ │ │ ├── orange_network_transmitter.json │ │ │ │ ├── orange_pattern_grid.json │ │ │ │ ├── orange_relay.json │ │ │ │ ├── orange_security_manager.json │ │ │ │ ├── orange_wireless_transmitter.json │ │ │ │ ├── pattern_grid.json │ │ │ │ ├── pink_controller.json │ │ │ │ ├── pink_crafter.json │ │ │ │ ├── pink_crafter_manager.json │ │ │ │ ├── pink_crafting_grid.json │ │ │ │ ├── pink_crafting_monitor.json │ │ │ │ ├── pink_creative_controller.json │ │ │ │ ├── pink_detector.json │ │ │ │ ├── pink_disk_manipulator.json │ │ │ │ ├── pink_fluid_grid.json │ │ │ │ ├── pink_grid.json │ │ │ │ ├── pink_network_receiver.json │ │ │ │ ├── pink_network_transmitter.json │ │ │ │ ├── pink_pattern_grid.json │ │ │ │ ├── pink_relay.json │ │ │ │ ├── pink_security_manager.json │ │ │ │ ├── pink_wireless_transmitter.json │ │ │ │ ├── purple_controller.json │ │ │ │ ├── purple_crafter.json │ │ │ │ ├── purple_crafter_manager.json │ │ │ │ ├── purple_crafting_grid.json │ │ │ │ ├── purple_crafting_monitor.json │ │ │ │ ├── purple_creative_controller.json │ │ │ │ ├── purple_detector.json │ │ │ │ ├── purple_disk_manipulator.json │ │ │ │ ├── purple_fluid_grid.json │ │ │ │ ├── purple_grid.json │ │ │ │ ├── purple_network_receiver.json │ │ │ │ ├── purple_network_transmitter.json │ │ │ │ ├── purple_pattern_grid.json │ │ │ │ ├── purple_relay.json │ │ │ │ ├── purple_security_manager.json │ │ │ │ ├── purple_wireless_transmitter.json │ │ │ │ ├── red_controller.json │ │ │ │ ├── red_crafter.json │ │ │ │ ├── red_crafter_manager.json │ │ │ │ ├── red_crafting_grid.json │ │ │ │ ├── red_crafting_monitor.json │ │ │ │ ├── red_creative_controller.json │ │ │ │ ├── red_detector.json │ │ │ │ ├── red_disk_manipulator.json │ │ │ │ ├── red_fluid_grid.json │ │ │ │ ├── red_grid.json │ │ │ │ ├── red_network_receiver.json │ │ │ │ ├── red_network_transmitter.json │ │ │ │ ├── red_pattern_grid.json │ │ │ │ ├── red_relay.json │ │ │ │ ├── red_security_manager.json │ │ │ │ ├── red_wireless_transmitter.json │ │ │ │ ├── relay.json │ │ │ │ ├── security_manager.json │ │ │ │ ├── white_controller.json │ │ │ │ ├── white_crafter.json │ │ │ │ ├── white_crafter_manager.json │ │ │ │ ├── white_crafting_grid.json │ │ │ │ ├── white_crafting_monitor.json │ │ │ │ ├── white_creative_controller.json │ │ │ │ ├── white_detector.json │ │ │ │ ├── white_disk_manipulator.json │ │ │ │ ├── white_fluid_grid.json │ │ │ │ ├── white_grid.json │ │ │ │ ├── white_network_receiver.json │ │ │ │ ├── white_network_transmitter.json │ │ │ │ ├── white_pattern_grid.json │ │ │ │ ├── white_relay.json │ │ │ │ ├── white_security_manager.json │ │ │ │ ├── white_wireless_transmitter.json │ │ │ │ ├── wireless_transmitter.json │ │ │ │ ├── yellow_controller.json │ │ │ │ ├── yellow_crafter.json │ │ │ │ ├── yellow_crafter_manager.json │ │ │ │ ├── yellow_crafting_grid.json │ │ │ │ ├── yellow_crafting_monitor.json │ │ │ │ ├── yellow_creative_controller.json │ │ │ │ ├── yellow_detector.json │ │ │ │ ├── yellow_disk_manipulator.json │ │ │ │ ├── yellow_fluid_grid.json │ │ │ │ ├── yellow_grid.json │ │ │ │ ├── yellow_network_receiver.json │ │ │ │ ├── yellow_network_transmitter.json │ │ │ │ ├── yellow_pattern_grid.json │ │ │ │ ├── yellow_relay.json │ │ │ │ ├── yellow_security_manager.json │ │ │ │ └── yellow_wireless_transmitter.json │ │ │ └── models/ │ │ │ ├── block/ │ │ │ │ ├── controller/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── nearly_off.json │ │ │ │ │ ├── nearly_on.json │ │ │ │ │ ├── off.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── crafter/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── crafter_manager/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── crafting_grid/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── crafting_monitor/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── detector/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── off.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── disk_manipulator/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── loader.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── fluid_grid/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── grid/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── network_receiver/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── network_transmitter/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── pattern_grid/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── relay/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ ├── security_manager/ │ │ │ │ │ ├── black.json │ │ │ │ │ ├── blue.json │ │ │ │ │ ├── brown.json │ │ │ │ │ ├── cyan.json │ │ │ │ │ ├── disconnected.json │ │ │ │ │ ├── gray.json │ │ │ │ │ ├── green.json │ │ │ │ │ ├── light_blue.json │ │ │ │ │ ├── light_gray.json │ │ │ │ │ ├── lime.json │ │ │ │ │ ├── magenta.json │ │ │ │ │ ├── orange.json │ │ │ │ │ ├── pink.json │ │ │ │ │ ├── purple.json │ │ │ │ │ ├── red.json │ │ │ │ │ ├── white.json │ │ │ │ │ └── yellow.json │ │ │ │ └── wireless_transmitter/ │ │ │ │ ├── black.json │ │ │ │ ├── blue.json │ │ │ │ ├── brown.json │ │ │ │ ├── cyan.json │ │ │ │ ├── disconnected.json │ │ │ │ ├── gray.json │ │ │ │ ├── green.json │ │ │ │ ├── light_blue.json │ │ │ │ ├── light_gray.json │ │ │ │ ├── lime.json │ │ │ │ ├── magenta.json │ │ │ │ ├── orange.json │ │ │ │ ├── pink.json │ │ │ │ ├── purple.json │ │ │ │ ├── red.json │ │ │ │ ├── white.json │ │ │ │ └── yellow.json │ │ │ └── item/ │ │ │ ├── black_controller.json │ │ │ ├── black_crafter.json │ │ │ ├── black_crafter_manager.json │ │ │ ├── black_crafting_grid.json │ │ │ ├── black_crafting_monitor.json │ │ │ ├── black_creative_controller.json │ │ │ ├── black_detector.json │ │ │ ├── black_disk_manipulator.json │ │ │ ├── black_fluid_grid.json │ │ │ ├── black_grid.json │ │ │ ├── black_network_receiver.json │ │ │ ├── black_network_transmitter.json │ │ │ ├── black_pattern_grid.json │ │ │ ├── black_relay.json │ │ │ ├── black_security_manager.json │ │ │ ├── black_wireless_transmitter.json │ │ │ ├── blue_controller.json │ │ │ ├── blue_crafter.json │ │ │ ├── blue_crafter_manager.json │ │ │ ├── blue_crafting_grid.json │ │ │ ├── blue_crafting_monitor.json │ │ │ ├── blue_creative_controller.json │ │ │ ├── blue_detector.json │ │ │ ├── blue_disk_manipulator.json │ │ │ ├── blue_fluid_grid.json │ │ │ ├── blue_grid.json │ │ │ ├── blue_network_receiver.json │ │ │ ├── blue_network_transmitter.json │ │ │ ├── blue_pattern_grid.json │ │ │ ├── blue_relay.json │ │ │ ├── blue_security_manager.json │ │ │ ├── blue_wireless_transmitter.json │ │ │ ├── brown_controller.json │ │ │ ├── brown_crafter.json │ │ │ ├── brown_crafter_manager.json │ │ │ ├── brown_crafting_grid.json │ │ │ ├── brown_crafting_monitor.json │ │ │ ├── brown_creative_controller.json │ │ │ ├── brown_detector.json │ │ │ ├── brown_disk_manipulator.json │ │ │ ├── brown_fluid_grid.json │ │ │ ├── brown_grid.json │ │ │ ├── brown_network_receiver.json │ │ │ ├── brown_network_transmitter.json │ │ │ ├── brown_pattern_grid.json │ │ │ ├── brown_relay.json │ │ │ ├── brown_security_manager.json │ │ │ ├── brown_wireless_transmitter.json │ │ │ ├── controller.json │ │ │ ├── crafter.json │ │ │ ├── crafter_manager.json │ │ │ ├── crafting_grid.json │ │ │ ├── crafting_monitor.json │ │ │ ├── creative_controller.json │ │ │ ├── cyan_controller.json │ │ │ ├── cyan_crafter.json │ │ │ ├── cyan_crafter_manager.json │ │ │ ├── cyan_crafting_grid.json │ │ │ ├── cyan_crafting_monitor.json │ │ │ ├── cyan_creative_controller.json │ │ │ ├── cyan_detector.json │ │ │ ├── cyan_disk_manipulator.json │ │ │ ├── cyan_fluid_grid.json │ │ │ ├── cyan_grid.json │ │ │ ├── cyan_network_receiver.json │ │ │ ├── cyan_network_transmitter.json │ │ │ ├── cyan_pattern_grid.json │ │ │ ├── cyan_relay.json │ │ │ ├── cyan_security_manager.json │ │ │ ├── cyan_wireless_transmitter.json │ │ │ ├── detector.json │ │ │ ├── disk_manipulator.json │ │ │ ├── fluid_grid.json │ │ │ ├── gray_controller.json │ │ │ ├── gray_crafter.json │ │ │ ├── gray_crafter_manager.json │ │ │ ├── gray_crafting_grid.json │ │ │ ├── gray_crafting_monitor.json │ │ │ ├── gray_creative_controller.json │ │ │ ├── gray_detector.json │ │ │ ├── gray_disk_manipulator.json │ │ │ ├── gray_fluid_grid.json │ │ │ ├── gray_grid.json │ │ │ ├── gray_network_receiver.json │ │ │ ├── gray_network_transmitter.json │ │ │ ├── gray_pattern_grid.json │ │ │ ├── gray_relay.json │ │ │ ├── gray_security_manager.json │ │ │ ├── gray_wireless_transmitter.json │ │ │ ├── green_controller.json │ │ │ ├── green_crafter.json │ │ │ ├── green_crafter_manager.json │ │ │ ├── green_crafting_grid.json │ │ │ ├── green_crafting_monitor.json │ │ │ ├── green_creative_controller.json │ │ │ ├── green_detector.json │ │ │ ├── green_disk_manipulator.json │ │ │ ├── green_fluid_grid.json │ │ │ ├── green_grid.json │ │ │ ├── green_network_receiver.json │ │ │ ├── green_network_transmitter.json │ │ │ ├── green_pattern_grid.json │ │ │ ├── green_relay.json │ │ │ ├── green_security_manager.json │ │ │ ├── green_wireless_transmitter.json │ │ │ ├── grid.json │ │ │ ├── light_gray_controller.json │ │ │ ├── light_gray_crafter.json │ │ │ ├── light_gray_crafter_manager.json │ │ │ ├── light_gray_crafting_grid.json │ │ │ ├── light_gray_crafting_monitor.json │ │ │ ├── light_gray_creative_controller.json │ │ │ ├── light_gray_detector.json │ │ │ ├── light_gray_disk_manipulator.json │ │ │ ├── light_gray_fluid_grid.json │ │ │ ├── light_gray_grid.json │ │ │ ├── light_gray_network_receiver.json │ │ │ ├── light_gray_network_transmitter.json │ │ │ ├── light_gray_pattern_grid.json │ │ │ ├── light_gray_relay.json │ │ │ ├── light_gray_security_manager.json │ │ │ ├── light_gray_wireless_transmitter.json │ │ │ ├── lime_controller.json │ │ │ ├── lime_crafter.json │ │ │ ├── lime_crafter_manager.json │ │ │ ├── lime_crafting_grid.json │ │ │ ├── lime_crafting_monitor.json │ │ │ ├── lime_creative_controller.json │ │ │ ├── lime_detector.json │ │ │ ├── lime_disk_manipulator.json │ │ │ ├── lime_fluid_grid.json │ │ │ ├── lime_grid.json │ │ │ ├── lime_network_receiver.json │ │ │ ├── lime_network_transmitter.json │ │ │ ├── lime_pattern_grid.json │ │ │ ├── lime_relay.json │ │ │ ├── lime_security_manager.json │ │ │ ├── lime_wireless_transmitter.json │ │ │ ├── magenta_controller.json │ │ │ ├── magenta_crafter.json │ │ │ ├── magenta_crafter_manager.json │ │ │ ├── magenta_crafting_grid.json │ │ │ ├── magenta_crafting_monitor.json │ │ │ ├── magenta_creative_controller.json │ │ │ ├── magenta_detector.json │ │ │ ├── magenta_disk_manipulator.json │ │ │ ├── magenta_fluid_grid.json │ │ │ ├── magenta_grid.json │ │ │ ├── magenta_network_receiver.json │ │ │ ├── magenta_network_transmitter.json │ │ │ ├── magenta_pattern_grid.json │ │ │ ├── magenta_relay.json │ │ │ ├── magenta_security_manager.json │ │ │ ├── magenta_wireless_transmitter.json │ │ │ ├── network_receiver.json │ │ │ ├── network_transmitter.json │ │ │ ├── orange_controller.json │ │ │ ├── orange_crafter.json │ │ │ ├── orange_crafter_manager.json │ │ │ ├── orange_crafting_grid.json │ │ │ ├── orange_crafting_monitor.json │ │ │ ├── orange_creative_controller.json │ │ │ ├── orange_detector.json │ │ │ ├── orange_disk_manipulator.json │ │ │ ├── orange_fluid_grid.json │ │ │ ├── orange_grid.json │ │ │ ├── orange_network_receiver.json │ │ │ ├── orange_network_transmitter.json │ │ │ ├── orange_pattern_grid.json │ │ │ ├── orange_relay.json │ │ │ ├── orange_security_manager.json │ │ │ ├── orange_wireless_transmitter.json │ │ │ ├── pattern_grid.json │ │ │ ├── pink_controller.json │ │ │ ├── pink_crafter.json │ │ │ ├── pink_crafter_manager.json │ │ │ ├── pink_crafting_grid.json │ │ │ ├── pink_crafting_monitor.json │ │ │ ├── pink_creative_controller.json │ │ │ ├── pink_detector.json │ │ │ ├── pink_disk_manipulator.json │ │ │ ├── pink_fluid_grid.json │ │ │ ├── pink_grid.json │ │ │ ├── pink_network_receiver.json │ │ │ ├── pink_network_transmitter.json │ │ │ ├── pink_pattern_grid.json │ │ │ ├── pink_relay.json │ │ │ ├── pink_security_manager.json │ │ │ ├── pink_wireless_transmitter.json │ │ │ ├── purple_controller.json │ │ │ ├── purple_crafter.json │ │ │ ├── purple_crafter_manager.json │ │ │ ├── purple_crafting_grid.json │ │ │ ├── purple_crafting_monitor.json │ │ │ ├── purple_creative_controller.json │ │ │ ├── purple_detector.json │ │ │ ├── purple_disk_manipulator.json │ │ │ ├── purple_fluid_grid.json │ │ │ ├── purple_grid.json │ │ │ ├── purple_network_receiver.json │ │ │ ├── purple_network_transmitter.json │ │ │ ├── purple_pattern_grid.json │ │ │ ├── purple_relay.json │ │ │ ├── purple_security_manager.json │ │ │ ├── purple_wireless_transmitter.json │ │ │ ├── red_controller.json │ │ │ ├── red_crafter.json │ │ │ ├── red_crafter_manager.json │ │ │ ├── red_crafting_grid.json │ │ │ ├── red_crafting_monitor.json │ │ │ ├── red_creative_controller.json │ │ │ ├── red_detector.json │ │ │ ├── red_disk_manipulator.json │ │ │ ├── red_fluid_grid.json │ │ │ ├── red_grid.json │ │ │ ├── red_network_receiver.json │ │ │ ├── red_network_transmitter.json │ │ │ ├── red_pattern_grid.json │ │ │ ├── red_relay.json │ │ │ ├── red_security_manager.json │ │ │ ├── red_wireless_transmitter.json │ │ │ ├── relay.json │ │ │ ├── security_manager.json │ │ │ ├── white_controller.json │ │ │ ├── white_crafter.json │ │ │ ├── white_crafter_manager.json │ │ │ ├── white_crafting_grid.json │ │ │ ├── white_crafting_monitor.json │ │ │ ├── white_creative_controller.json │ │ │ ├── white_detector.json │ │ │ ├── white_disk_manipulator.json │ │ │ ├── white_fluid_grid.json │ │ │ ├── white_grid.json │ │ │ ├── white_network_receiver.json │ │ │ ├── white_network_transmitter.json │ │ │ ├── white_pattern_grid.json │ │ │ ├── white_relay.json │ │ │ ├── white_security_manager.json │ │ │ ├── white_wireless_transmitter.json │ │ │ ├── wireless_transmitter.json │ │ │ ├── yellow_controller.json │ │ │ ├── yellow_crafter.json │ │ │ ├── yellow_crafter_manager.json │ │ │ ├── yellow_crafting_grid.json │ │ │ ├── yellow_crafting_monitor.json │ │ │ ├── yellow_creative_controller.json │ │ │ ├── yellow_detector.json │ │ │ ├── yellow_disk_manipulator.json │ │ │ ├── yellow_fluid_grid.json │ │ │ ├── yellow_grid.json │ │ │ ├── yellow_network_receiver.json │ │ │ ├── yellow_network_transmitter.json │ │ │ ├── yellow_pattern_grid.json │ │ │ ├── yellow_relay.json │ │ │ ├── yellow_security_manager.json │ │ │ └── yellow_wireless_transmitter.json │ │ └── data/ │ │ ├── forge/ │ │ │ └── tags/ │ │ │ └── blocks/ │ │ │ └── relocation_not_supported.json │ │ ├── packingtape/ │ │ │ └── tags/ │ │ │ └── block_entity_type/ │ │ │ └── blacklist/ │ │ │ └── problematic.json │ │ └── refinedstorage/ │ │ ├── advancements/ │ │ │ └── recipes/ │ │ │ └── misc/ │ │ │ ├── coloring_recipes/ │ │ │ │ ├── black_controller.json │ │ │ │ ├── black_crafter.json │ │ │ │ ├── black_crafter_manager.json │ │ │ │ ├── black_crafting_grid.json │ │ │ │ ├── black_crafting_monitor.json │ │ │ │ ├── black_detector.json │ │ │ │ ├── black_disk_manipulator.json │ │ │ │ ├── black_fluid_grid.json │ │ │ │ ├── black_grid.json │ │ │ │ ├── black_network_receiver.json │ │ │ │ ├── black_network_transmitter.json │ │ │ │ ├── black_pattern_grid.json │ │ │ │ ├── black_relay.json │ │ │ │ ├── black_security_manager.json │ │ │ │ ├── black_wireless_transmitter.json │ │ │ │ ├── blue_controller.json │ │ │ │ ├── blue_crafter.json │ │ │ │ ├── blue_crafter_manager.json │ │ │ │ ├── blue_crafting_grid.json │ │ │ │ ├── blue_crafting_monitor.json │ │ │ │ ├── blue_detector.json │ │ │ │ ├── blue_disk_manipulator.json │ │ │ │ ├── blue_fluid_grid.json │ │ │ │ ├── blue_grid.json │ │ │ │ ├── blue_network_receiver.json │ │ │ │ ├── blue_network_transmitter.json │ │ │ │ ├── blue_pattern_grid.json │ │ │ │ ├── blue_relay.json │ │ │ │ ├── blue_security_manager.json │ │ │ │ ├── blue_wireless_transmitter.json │ │ │ │ ├── brown_controller.json │ │ │ │ ├── brown_crafter.json │ │ │ │ ├── brown_crafter_manager.json │ │ │ │ ├── brown_crafting_grid.json │ │ │ │ ├── brown_crafting_monitor.json │ │ │ │ ├── brown_detector.json │ │ │ │ ├── brown_disk_manipulator.json │ │ │ │ ├── brown_fluid_grid.json │ │ │ │ ├── brown_grid.json │ │ │ │ ├── brown_network_receiver.json │ │ │ │ ├── brown_network_transmitter.json │ │ │ │ ├── brown_pattern_grid.json │ │ │ │ ├── brown_relay.json │ │ │ │ ├── brown_security_manager.json │ │ │ │ ├── brown_wireless_transmitter.json │ │ │ │ ├── controller.json │ │ │ │ ├── crafter.json │ │ │ │ ├── crafter_manager.json │ │ │ │ ├── crafting_grid.json │ │ │ │ ├── crafting_monitor.json │ │ │ │ ├── cyan_controller.json │ │ │ │ ├── cyan_crafter.json │ │ │ │ ├── cyan_crafter_manager.json │ │ │ │ ├── cyan_crafting_grid.json │ │ │ │ ├── cyan_crafting_monitor.json │ │ │ │ ├── cyan_detector.json │ │ │ │ ├── cyan_disk_manipulator.json │ │ │ │ ├── cyan_fluid_grid.json │ │ │ │ ├── cyan_grid.json │ │ │ │ ├── cyan_network_receiver.json │ │ │ │ ├── cyan_network_transmitter.json │ │ │ │ ├── cyan_pattern_grid.json │ │ │ │ ├── cyan_relay.json │ │ │ │ ├── cyan_security_manager.json │ │ │ │ ├── cyan_wireless_transmitter.json │ │ │ │ ├── detector.json │ │ │ │ ├── disk_manipulator.json │ │ │ │ ├── fluid_grid.json │ │ │ │ ├── gray_controller.json │ │ │ │ ├── gray_crafter.json │ │ │ │ ├── gray_crafter_manager.json │ │ │ │ ├── gray_crafting_grid.json │ │ │ │ ├── gray_crafting_monitor.json │ │ │ │ ├── gray_detector.json │ │ │ │ ├── gray_disk_manipulator.json │ │ │ │ ├── gray_fluid_grid.json │ │ │ │ ├── gray_grid.json │ │ │ │ ├── gray_network_receiver.json │ │ │ │ ├── gray_network_transmitter.json │ │ │ │ ├── gray_pattern_grid.json │ │ │ │ ├── gray_relay.json │ │ │ │ ├── gray_security_manager.json │ │ │ │ ├── gray_wireless_transmitter.json │ │ │ │ ├── green_controller.json │ │ │ │ ├── green_crafter.json │ │ │ │ ├── green_crafter_manager.json │ │ │ │ ├── green_crafting_grid.json │ │ │ │ ├── green_crafting_monitor.json │ │ │ │ ├── green_detector.json │ │ │ │ ├── green_disk_manipulator.json │ │ │ │ ├── green_fluid_grid.json │ │ │ │ ├── green_grid.json │ │ │ │ ├── green_network_receiver.json │ │ │ │ ├── green_network_transmitter.json │ │ │ │ ├── green_pattern_grid.json │ │ │ │ ├── green_relay.json │ │ │ │ ├── green_security_manager.json │ │ │ │ ├── green_wireless_transmitter.json │ │ │ │ ├── grid.json │ │ │ │ ├── light_gray_controller.json │ │ │ │ ├── light_gray_crafter.json │ │ │ │ ├── light_gray_crafter_manager.json │ │ │ │ ├── light_gray_crafting_grid.json │ │ │ │ ├── light_gray_crafting_monitor.json │ │ │ │ ├── light_gray_detector.json │ │ │ │ ├── light_gray_disk_manipulator.json │ │ │ │ ├── light_gray_fluid_grid.json │ │ │ │ ├── light_gray_grid.json │ │ │ │ ├── light_gray_network_receiver.json │ │ │ │ ├── light_gray_network_transmitter.json │ │ │ │ ├── light_gray_pattern_grid.json │ │ │ │ ├── light_gray_relay.json │ │ │ │ ├── light_gray_security_manager.json │ │ │ │ ├── light_gray_wireless_transmitter.json │ │ │ │ ├── lime_controller.json │ │ │ │ ├── lime_crafter.json │ │ │ │ ├── lime_crafter_manager.json │ │ │ │ ├── lime_crafting_grid.json │ │ │ │ ├── lime_crafting_monitor.json │ │ │ │ ├── lime_detector.json │ │ │ │ ├── lime_disk_manipulator.json │ │ │ │ ├── lime_fluid_grid.json │ │ │ │ ├── lime_grid.json │ │ │ │ ├── lime_network_receiver.json │ │ │ │ ├── lime_network_transmitter.json │ │ │ │ ├── lime_pattern_grid.json │ │ │ │ ├── lime_relay.json │ │ │ │ ├── lime_security_manager.json │ │ │ │ ├── lime_wireless_transmitter.json │ │ │ │ ├── magenta_controller.json │ │ │ │ ├── magenta_crafter.json │ │ │ │ ├── magenta_crafter_manager.json │ │ │ │ ├── magenta_crafting_grid.json │ │ │ │ ├── magenta_crafting_monitor.json │ │ │ │ ├── magenta_detector.json │ │ │ │ ├── magenta_disk_manipulator.json │ │ │ │ ├── magenta_fluid_grid.json │ │ │ │ ├── magenta_grid.json │ │ │ │ ├── magenta_network_receiver.json │ │ │ │ ├── magenta_network_transmitter.json │ │ │ │ ├── magenta_pattern_grid.json │ │ │ │ ├── magenta_relay.json │ │ │ │ ├── magenta_security_manager.json │ │ │ │ ├── magenta_wireless_transmitter.json │ │ │ │ ├── network_receiver.json │ │ │ │ ├── network_transmitter.json │ │ │ │ ├── orange_controller.json │ │ │ │ ├── orange_crafter.json │ │ │ │ ├── orange_crafter_manager.json │ │ │ │ ├── orange_crafting_grid.json │ │ │ │ ├── orange_crafting_monitor.json │ │ │ │ ├── orange_detector.json │ │ │ │ ├── orange_disk_manipulator.json │ │ │ │ ├── orange_fluid_grid.json │ │ │ │ ├── orange_grid.json │ │ │ │ ├── orange_network_receiver.json │ │ │ │ ├── orange_network_transmitter.json │ │ │ │ ├── orange_pattern_grid.json │ │ │ │ ├── orange_relay.json │ │ │ │ ├── orange_security_manager.json │ │ │ │ ├── orange_wireless_transmitter.json │ │ │ │ ├── pattern_grid.json │ │ │ │ ├── pink_controller.json │ │ │ │ ├── pink_crafter.json │ │ │ │ ├── pink_crafter_manager.json │ │ │ │ ├── pink_crafting_grid.json │ │ │ │ ├── pink_crafting_monitor.json │ │ │ │ ├── pink_detector.json │ │ │ │ ├── pink_disk_manipulator.json │ │ │ │ ├── pink_fluid_grid.json │ │ │ │ ├── pink_grid.json │ │ │ │ ├── pink_network_receiver.json │ │ │ │ ├── pink_network_transmitter.json │ │ │ │ ├── pink_pattern_grid.json │ │ │ │ ├── pink_relay.json │ │ │ │ ├── pink_security_manager.json │ │ │ │ ├── pink_wireless_transmitter.json │ │ │ │ ├── purple_controller.json │ │ │ │ ├── purple_crafter.json │ │ │ │ ├── purple_crafter_manager.json │ │ │ │ ├── purple_crafting_grid.json │ │ │ │ ├── purple_crafting_monitor.json │ │ │ │ ├── purple_detector.json │ │ │ │ ├── purple_disk_manipulator.json │ │ │ │ ├── purple_fluid_grid.json │ │ │ │ ├── purple_grid.json │ │ │ │ ├── purple_network_receiver.json │ │ │ │ ├── purple_network_transmitter.json │ │ │ │ ├── purple_pattern_grid.json │ │ │ │ ├── purple_relay.json │ │ │ │ ├── purple_security_manager.json │ │ │ │ ├── purple_wireless_transmitter.json │ │ │ │ ├── red_controller.json │ │ │ │ ├── red_crafter.json │ │ │ │ ├── red_crafter_manager.json │ │ │ │ ├── red_crafting_grid.json │ │ │ │ ├── red_crafting_monitor.json │ │ │ │ ├── red_detector.json │ │ │ │ ├── red_disk_manipulator.json │ │ │ │ ├── red_fluid_grid.json │ │ │ │ ├── red_grid.json │ │ │ │ ├── red_network_receiver.json │ │ │ │ ├── red_network_transmitter.json │ │ │ │ ├── red_pattern_grid.json │ │ │ │ ├── red_relay.json │ │ │ │ ├── red_security_manager.json │ │ │ │ ├── red_wireless_transmitter.json │ │ │ │ ├── relay.json │ │ │ │ ├── security_manager.json │ │ │ │ ├── white_controller.json │ │ │ │ ├── white_crafter.json │ │ │ │ ├── white_crafter_manager.json │ │ │ │ ├── white_crafting_grid.json │ │ │ │ ├── white_crafting_monitor.json │ │ │ │ ├── white_detector.json │ │ │ │ ├── white_disk_manipulator.json │ │ │ │ ├── white_fluid_grid.json │ │ │ │ ├── white_grid.json │ │ │ │ ├── white_network_receiver.json │ │ │ │ ├── white_network_transmitter.json │ │ │ │ ├── white_pattern_grid.json │ │ │ │ ├── white_relay.json │ │ │ │ ├── white_security_manager.json │ │ │ │ ├── white_wireless_transmitter.json │ │ │ │ ├── wireless_transmitter.json │ │ │ │ ├── yellow_controller.json │ │ │ │ ├── yellow_crafter.json │ │ │ │ ├── yellow_crafter_manager.json │ │ │ │ ├── yellow_crafting_grid.json │ │ │ │ ├── yellow_crafting_monitor.json │ │ │ │ ├── yellow_detector.json │ │ │ │ ├── yellow_disk_manipulator.json │ │ │ │ ├── yellow_fluid_grid.json │ │ │ │ ├── yellow_grid.json │ │ │ │ ├── yellow_network_receiver.json │ │ │ │ ├── yellow_network_transmitter.json │ │ │ │ ├── yellow_pattern_grid.json │ │ │ │ ├── yellow_relay.json │ │ │ │ ├── yellow_security_manager.json │ │ │ │ └── yellow_wireless_transmitter.json │ │ │ ├── crafting_grid/ │ │ │ │ ├── black_crafting_grid.json │ │ │ │ ├── blue_crafting_grid.json │ │ │ │ ├── brown_crafting_grid.json │ │ │ │ ├── crafting_grid.json │ │ │ │ ├── cyan_crafting_grid.json │ │ │ │ ├── gray_crafting_grid.json │ │ │ │ ├── green_crafting_grid.json │ │ │ │ ├── light_gray_crafting_grid.json │ │ │ │ ├── lime_crafting_grid.json │ │ │ │ ├── magenta_crafting_grid.json │ │ │ │ ├── orange_crafting_grid.json │ │ │ │ ├── pink_crafting_grid.json │ │ │ │ ├── purple_crafting_grid.json │ │ │ │ ├── red_crafting_grid.json │ │ │ │ ├── white_crafting_grid.json │ │ │ │ └── yellow_crafting_grid.json │ │ │ ├── fluid_grid/ │ │ │ │ ├── black_fluid_grid.json │ │ │ │ ├── blue_fluid_grid.json │ │ │ │ ├── brown_fluid_grid.json │ │ │ │ ├── cyan_fluid_grid.json │ │ │ │ ├── fluid_grid.json │ │ │ │ ├── gray_fluid_grid.json │ │ │ │ ├── green_fluid_grid.json │ │ │ │ ├── light_gray_fluid_grid.json │ │ │ │ ├── lime_fluid_grid.json │ │ │ │ ├── magenta_fluid_grid.json │ │ │ │ ├── orange_fluid_grid.json │ │ │ │ ├── pink_fluid_grid.json │ │ │ │ ├── purple_fluid_grid.json │ │ │ │ ├── red_fluid_grid.json │ │ │ │ ├── white_fluid_grid.json │ │ │ │ └── yellow_fluid_grid.json │ │ │ └── pattern_grid/ │ │ │ ├── black_pattern_grid.json │ │ │ ├── blue_pattern_grid.json │ │ │ ├── brown_pattern_grid.json │ │ │ ├── cyan_pattern_grid.json │ │ │ ├── gray_pattern_grid.json │ │ │ ├── green_pattern_grid.json │ │ │ ├── light_gray_pattern_grid.json │ │ │ ├── lime_pattern_grid.json │ │ │ ├── magenta_pattern_grid.json │ │ │ ├── orange_pattern_grid.json │ │ │ ├── pattern_grid.json │ │ │ ├── pink_pattern_grid.json │ │ │ ├── purple_pattern_grid.json │ │ │ ├── red_pattern_grid.json │ │ │ ├── white_pattern_grid.json │ │ │ └── yellow_pattern_grid.json │ │ ├── loot_tables/ │ │ │ └── blocks/ │ │ │ ├── black_controller.json │ │ │ ├── black_crafter.json │ │ │ ├── black_crafter_manager.json │ │ │ ├── black_crafting_grid.json │ │ │ ├── black_crafting_monitor.json │ │ │ ├── black_creative_controller.json │ │ │ ├── black_detector.json │ │ │ ├── black_disk_manipulator.json │ │ │ ├── black_fluid_grid.json │ │ │ ├── black_grid.json │ │ │ ├── black_network_receiver.json │ │ │ ├── black_network_transmitter.json │ │ │ ├── black_pattern_grid.json │ │ │ ├── black_relay.json │ │ │ ├── black_security_manager.json │ │ │ ├── black_wireless_transmitter.json │ │ │ ├── blue_controller.json │ │ │ ├── blue_crafter.json │ │ │ ├── blue_crafter_manager.json │ │ │ ├── blue_crafting_grid.json │ │ │ ├── blue_crafting_monitor.json │ │ │ ├── blue_creative_controller.json │ │ │ ├── blue_detector.json │ │ │ ├── blue_disk_manipulator.json │ │ │ ├── blue_fluid_grid.json │ │ │ ├── blue_grid.json │ │ │ ├── blue_network_receiver.json │ │ │ ├── blue_network_transmitter.json │ │ │ ├── blue_pattern_grid.json │ │ │ ├── blue_relay.json │ │ │ ├── blue_security_manager.json │ │ │ ├── blue_wireless_transmitter.json │ │ │ ├── brown_controller.json │ │ │ ├── brown_crafter.json │ │ │ ├── brown_crafter_manager.json │ │ │ ├── brown_crafting_grid.json │ │ │ ├── brown_crafting_monitor.json │ │ │ ├── brown_creative_controller.json │ │ │ ├── brown_detector.json │ │ │ ├── brown_disk_manipulator.json │ │ │ ├── brown_fluid_grid.json │ │ │ ├── brown_grid.json │ │ │ ├── brown_network_receiver.json │ │ │ ├── brown_network_transmitter.json │ │ │ ├── brown_pattern_grid.json │ │ │ ├── brown_relay.json │ │ │ ├── brown_security_manager.json │ │ │ ├── brown_wireless_transmitter.json │ │ │ ├── controller.json │ │ │ ├── crafter.json │ │ │ ├── crafter_manager.json │ │ │ ├── crafting_grid.json │ │ │ ├── crafting_monitor.json │ │ │ ├── creative_controller.json │ │ │ ├── cyan_controller.json │ │ │ ├── cyan_crafter.json │ │ │ ├── cyan_crafter_manager.json │ │ │ ├── cyan_crafting_grid.json │ │ │ ├── cyan_crafting_monitor.json │ │ │ ├── cyan_creative_controller.json │ │ │ ├── cyan_detector.json │ │ │ ├── cyan_disk_manipulator.json │ │ │ ├── cyan_fluid_grid.json │ │ │ ├── cyan_grid.json │ │ │ ├── cyan_network_receiver.json │ │ │ ├── cyan_network_transmitter.json │ │ │ ├── cyan_pattern_grid.json │ │ │ ├── cyan_relay.json │ │ │ ├── cyan_security_manager.json │ │ │ ├── cyan_wireless_transmitter.json │ │ │ ├── detector.json │ │ │ ├── disk_manipulator.json │ │ │ ├── fluid_grid.json │ │ │ ├── gray_controller.json │ │ │ ├── gray_crafter.json │ │ │ ├── gray_crafter_manager.json │ │ │ ├── gray_crafting_grid.json │ │ │ ├── gray_crafting_monitor.json │ │ │ ├── gray_creative_controller.json │ │ │ ├── gray_detector.json │ │ │ ├── gray_disk_manipulator.json │ │ │ ├── gray_fluid_grid.json │ │ │ ├── gray_grid.json │ │ │ ├── gray_network_receiver.json │ │ │ ├── gray_network_transmitter.json │ │ │ ├── gray_pattern_grid.json │ │ │ ├── gray_relay.json │ │ │ ├── gray_security_manager.json │ │ │ ├── gray_wireless_transmitter.json │ │ │ ├── green_controller.json │ │ │ ├── green_crafter.json │ │ │ ├── green_crafter_manager.json │ │ │ ├── green_crafting_grid.json │ │ │ ├── green_crafting_monitor.json │ │ │ ├── green_creative_controller.json │ │ │ ├── green_detector.json │ │ │ ├── green_disk_manipulator.json │ │ │ ├── green_fluid_grid.json │ │ │ ├── green_grid.json │ │ │ ├── green_network_receiver.json │ │ │ ├── green_network_transmitter.json │ │ │ ├── green_pattern_grid.json │ │ │ ├── green_relay.json │ │ │ ├── green_security_manager.json │ │ │ ├── green_wireless_transmitter.json │ │ │ ├── grid.json │ │ │ ├── light_gray_controller.json │ │ │ ├── light_gray_crafter.json │ │ │ ├── light_gray_crafter_manager.json │ │ │ ├── light_gray_crafting_grid.json │ │ │ ├── light_gray_crafting_monitor.json │ │ │ ├── light_gray_creative_controller.json │ │ │ ├── light_gray_detector.json │ │ │ ├── light_gray_disk_manipulator.json │ │ │ ├── light_gray_fluid_grid.json │ │ │ ├── light_gray_grid.json │ │ │ ├── light_gray_network_receiver.json │ │ │ ├── light_gray_network_transmitter.json │ │ │ ├── light_gray_pattern_grid.json │ │ │ ├── light_gray_relay.json │ │ │ ├── light_gray_security_manager.json │ │ │ ├── light_gray_wireless_transmitter.json │ │ │ ├── lime_controller.json │ │ │ ├── lime_crafter.json │ │ │ ├── lime_crafter_manager.json │ │ │ ├── lime_crafting_grid.json │ │ │ ├── lime_crafting_monitor.json │ │ │ ├── lime_creative_controller.json │ │ │ ├── lime_detector.json │ │ │ ├── lime_disk_manipulator.json │ │ │ ├── lime_fluid_grid.json │ │ │ ├── lime_grid.json │ │ │ ├── lime_network_receiver.json │ │ │ ├── lime_network_transmitter.json │ │ │ ├── lime_pattern_grid.json │ │ │ ├── lime_relay.json │ │ │ ├── lime_security_manager.json │ │ │ ├── lime_wireless_transmitter.json │ │ │ ├── magenta_controller.json │ │ │ ├── magenta_crafter.json │ │ │ ├── magenta_crafter_manager.json │ │ │ ├── magenta_crafting_grid.json │ │ │ ├── magenta_crafting_monitor.json │ │ │ ├── magenta_creative_controller.json │ │ │ ├── magenta_detector.json │ │ │ ├── magenta_disk_manipulator.json │ │ │ ├── magenta_fluid_grid.json │ │ │ ├── magenta_grid.json │ │ │ ├── magenta_network_receiver.json │ │ │ ├── magenta_network_transmitter.json │ │ │ ├── magenta_pattern_grid.json │ │ │ ├── magenta_relay.json │ │ │ ├── magenta_security_manager.json │ │ │ ├── magenta_wireless_transmitter.json │ │ │ ├── network_receiver.json │ │ │ ├── network_transmitter.json │ │ │ ├── orange_controller.json │ │ │ ├── orange_crafter.json │ │ │ ├── orange_crafter_manager.json │ │ │ ├── orange_crafting_grid.json │ │ │ ├── orange_crafting_monitor.json │ │ │ ├── orange_creative_controller.json │ │ │ ├── orange_detector.json │ │ │ ├── orange_disk_manipulator.json │ │ │ ├── orange_fluid_grid.json │ │ │ ├── orange_grid.json │ │ │ ├── orange_network_receiver.json │ │ │ ├── orange_network_transmitter.json │ │ │ ├── orange_pattern_grid.json │ │ │ ├── orange_relay.json │ │ │ ├── orange_security_manager.json │ │ │ ├── orange_wireless_transmitter.json │ │ │ ├── pattern_grid.json │ │ │ ├── pink_controller.json │ │ │ ├── pink_crafter.json │ │ │ ├── pink_crafter_manager.json │ │ │ ├── pink_crafting_grid.json │ │ │ ├── pink_crafting_monitor.json │ │ │ ├── pink_creative_controller.json │ │ │ ├── pink_detector.json │ │ │ ├── pink_disk_manipulator.json │ │ │ ├── pink_fluid_grid.json │ │ │ ├── pink_grid.json │ │ │ ├── pink_network_receiver.json │ │ │ ├── pink_network_transmitter.json │ │ │ ├── pink_pattern_grid.json │ │ │ ├── pink_relay.json │ │ │ ├── pink_security_manager.json │ │ │ ├── pink_wireless_transmitter.json │ │ │ ├── purple_controller.json │ │ │ ├── purple_crafter.json │ │ │ ├── purple_crafter_manager.json │ │ │ ├── purple_crafting_grid.json │ │ │ ├── purple_crafting_monitor.json │ │ │ ├── purple_creative_controller.json │ │ │ ├── purple_detector.json │ │ │ ├── purple_disk_manipulator.json │ │ │ ├── purple_fluid_grid.json │ │ │ ├── purple_grid.json │ │ │ ├── purple_network_receiver.json │ │ │ ├── purple_network_transmitter.json │ │ │ ├── purple_pattern_grid.json │ │ │ ├── purple_relay.json │ │ │ ├── purple_security_manager.json │ │ │ ├── purple_wireless_transmitter.json │ │ │ ├── red_controller.json │ │ │ ├── red_crafter.json │ │ │ ├── red_crafter_manager.json │ │ │ ├── red_crafting_grid.json │ │ │ ├── red_crafting_monitor.json │ │ │ ├── red_creative_controller.json │ │ │ ├── red_detector.json │ │ │ ├── red_disk_manipulator.json │ │ │ ├── red_fluid_grid.json │ │ │ ├── red_grid.json │ │ │ ├── red_network_receiver.json │ │ │ ├── red_network_transmitter.json │ │ │ ├── red_pattern_grid.json │ │ │ ├── red_relay.json │ │ │ ├── red_security_manager.json │ │ │ ├── red_wireless_transmitter.json │ │ │ ├── relay.json │ │ │ ├── security_manager.json │ │ │ ├── white_controller.json │ │ │ ├── white_crafter.json │ │ │ ├── white_crafter_manager.json │ │ │ ├── white_crafting_grid.json │ │ │ ├── white_crafting_monitor.json │ │ │ ├── white_creative_controller.json │ │ │ ├── white_detector.json │ │ │ ├── white_disk_manipulator.json │ │ │ ├── white_fluid_grid.json │ │ │ ├── white_grid.json │ │ │ ├── white_network_receiver.json │ │ │ ├── white_network_transmitter.json │ │ │ ├── white_pattern_grid.json │ │ │ ├── white_relay.json │ │ │ ├── white_security_manager.json │ │ │ ├── white_wireless_transmitter.json │ │ │ ├── wireless_transmitter.json │ │ │ ├── yellow_controller.json │ │ │ ├── yellow_crafter.json │ │ │ ├── yellow_crafter_manager.json │ │ │ ├── yellow_crafting_grid.json │ │ │ ├── yellow_crafting_monitor.json │ │ │ ├── yellow_creative_controller.json │ │ │ ├── yellow_detector.json │ │ │ ├── yellow_disk_manipulator.json │ │ │ ├── yellow_fluid_grid.json │ │ │ ├── yellow_grid.json │ │ │ ├── yellow_network_receiver.json │ │ │ ├── yellow_network_transmitter.json │ │ │ ├── yellow_pattern_grid.json │ │ │ ├── yellow_relay.json │ │ │ ├── yellow_security_manager.json │ │ │ └── yellow_wireless_transmitter.json │ │ ├── recipes/ │ │ │ ├── coloring_recipes/ │ │ │ │ ├── black_controller.json │ │ │ │ ├── black_crafter.json │ │ │ │ ├── black_crafter_manager.json │ │ │ │ ├── black_crafting_grid.json │ │ │ │ ├── black_crafting_monitor.json │ │ │ │ ├── black_detector.json │ │ │ │ ├── black_disk_manipulator.json │ │ │ │ ├── black_fluid_grid.json │ │ │ │ ├── black_grid.json │ │ │ │ ├── black_network_receiver.json │ │ │ │ ├── black_network_transmitter.json │ │ │ │ ├── black_pattern_grid.json │ │ │ │ ├── black_relay.json │ │ │ │ ├── black_security_manager.json │ │ │ │ ├── black_wireless_transmitter.json │ │ │ │ ├── blue_controller.json │ │ │ │ ├── blue_crafter.json │ │ │ │ ├── blue_crafter_manager.json │ │ │ │ ├── blue_crafting_grid.json │ │ │ │ ├── blue_crafting_monitor.json │ │ │ │ ├── blue_detector.json │ │ │ │ ├── blue_disk_manipulator.json │ │ │ │ ├── blue_fluid_grid.json │ │ │ │ ├── blue_grid.json │ │ │ │ ├── blue_network_receiver.json │ │ │ │ ├── blue_network_transmitter.json │ │ │ │ ├── blue_pattern_grid.json │ │ │ │ ├── blue_relay.json │ │ │ │ ├── blue_security_manager.json │ │ │ │ ├── blue_wireless_transmitter.json │ │ │ │ ├── brown_controller.json │ │ │ │ ├── brown_crafter.json │ │ │ │ ├── brown_crafter_manager.json │ │ │ │ ├── brown_crafting_grid.json │ │ │ │ ├── brown_crafting_monitor.json │ │ │ │ ├── brown_detector.json │ │ │ │ ├── brown_disk_manipulator.json │ │ │ │ ├── brown_fluid_grid.json │ │ │ │ ├── brown_grid.json │ │ │ │ ├── brown_network_receiver.json │ │ │ │ ├── brown_network_transmitter.json │ │ │ │ ├── brown_pattern_grid.json │ │ │ │ ├── brown_relay.json │ │ │ │ ├── brown_security_manager.json │ │ │ │ ├── brown_wireless_transmitter.json │ │ │ │ ├── controller.json │ │ │ │ ├── crafter.json │ │ │ │ ├── crafter_manager.json │ │ │ │ ├── crafting_grid.json │ │ │ │ ├── crafting_monitor.json │ │ │ │ ├── cyan_controller.json │ │ │ │ ├── cyan_crafter.json │ │ │ │ ├── cyan_crafter_manager.json │ │ │ │ ├── cyan_crafting_grid.json │ │ │ │ ├── cyan_crafting_monitor.json │ │ │ │ ├── cyan_detector.json │ │ │ │ ├── cyan_disk_manipulator.json │ │ │ │ ├── cyan_fluid_grid.json │ │ │ │ ├── cyan_grid.json │ │ │ │ ├── cyan_network_receiver.json │ │ │ │ ├── cyan_network_transmitter.json │ │ │ │ ├── cyan_pattern_grid.json │ │ │ │ ├── cyan_relay.json │ │ │ │ ├── cyan_security_manager.json │ │ │ │ ├── cyan_wireless_transmitter.json │ │ │ │ ├── detector.json │ │ │ │ ├── disk_manipulator.json │ │ │ │ ├── fluid_grid.json │ │ │ │ ├── gray_controller.json │ │ │ │ ├── gray_crafter.json │ │ │ │ ├── gray_crafter_manager.json │ │ │ │ ├── gray_crafting_grid.json │ │ │ │ ├── gray_crafting_monitor.json │ │ │ │ ├── gray_detector.json │ │ │ │ ├── gray_disk_manipulator.json │ │ │ │ ├── gray_fluid_grid.json │ │ │ │ ├── gray_grid.json │ │ │ │ ├── gray_network_receiver.json │ │ │ │ ├── gray_network_transmitter.json │ │ │ │ ├── gray_pattern_grid.json │ │ │ │ ├── gray_relay.json │ │ │ │ ├── gray_security_manager.json │ │ │ │ ├── gray_wireless_transmitter.json │ │ │ │ ├── green_controller.json │ │ │ │ ├── green_crafter.json │ │ │ │ ├── green_crafter_manager.json │ │ │ │ ├── green_crafting_grid.json │ │ │ │ ├── green_crafting_monitor.json │ │ │ │ ├── green_detector.json │ │ │ │ ├── green_disk_manipulator.json │ │ │ │ ├── green_fluid_grid.json │ │ │ │ ├── green_grid.json │ │ │ │ ├── green_network_receiver.json │ │ │ │ ├── green_network_transmitter.json │ │ │ │ ├── green_pattern_grid.json │ │ │ │ ├── green_relay.json │ │ │ │ ├── green_security_manager.json │ │ │ │ ├── green_wireless_transmitter.json │ │ │ │ ├── grid.json │ │ │ │ ├── light_gray_controller.json │ │ │ │ ├── light_gray_crafter.json │ │ │ │ ├── light_gray_crafter_manager.json │ │ │ │ ├── light_gray_crafting_grid.json │ │ │ │ ├── light_gray_crafting_monitor.json │ │ │ │ ├── light_gray_detector.json │ │ │ │ ├── light_gray_disk_manipulator.json │ │ │ │ ├── light_gray_fluid_grid.json │ │ │ │ ├── light_gray_grid.json │ │ │ │ ├── light_gray_network_receiver.json │ │ │ │ ├── light_gray_network_transmitter.json │ │ │ │ ├── light_gray_pattern_grid.json │ │ │ │ ├── light_gray_relay.json │ │ │ │ ├── light_gray_security_manager.json │ │ │ │ ├── light_gray_wireless_transmitter.json │ │ │ │ ├── lime_controller.json │ │ │ │ ├── lime_crafter.json │ │ │ │ ├── lime_crafter_manager.json │ │ │ │ ├── lime_crafting_grid.json │ │ │ │ ├── lime_crafting_monitor.json │ │ │ │ ├── lime_detector.json │ │ │ │ ├── lime_disk_manipulator.json │ │ │ │ ├── lime_fluid_grid.json │ │ │ │ ├── lime_grid.json │ │ │ │ ├── lime_network_receiver.json │ │ │ │ ├── lime_network_transmitter.json │ │ │ │ ├── lime_pattern_grid.json │ │ │ │ ├── lime_relay.json │ │ │ │ ├── lime_security_manager.json │ │ │ │ ├── lime_wireless_transmitter.json │ │ │ │ ├── magenta_controller.json │ │ │ │ ├── magenta_crafter.json │ │ │ │ ├── magenta_crafter_manager.json │ │ │ │ ├── magenta_crafting_grid.json │ │ │ │ ├── magenta_crafting_monitor.json │ │ │ │ ├── magenta_detector.json │ │ │ │ ├── magenta_disk_manipulator.json │ │ │ │ ├── magenta_fluid_grid.json │ │ │ │ ├── magenta_grid.json │ │ │ │ ├── magenta_network_receiver.json │ │ │ │ ├── magenta_network_transmitter.json │ │ │ │ ├── magenta_pattern_grid.json │ │ │ │ ├── magenta_relay.json │ │ │ │ ├── magenta_security_manager.json │ │ │ │ ├── magenta_wireless_transmitter.json │ │ │ │ ├── network_receiver.json │ │ │ │ ├── network_transmitter.json │ │ │ │ ├── orange_controller.json │ │ │ │ ├── orange_crafter.json │ │ │ │ ├── orange_crafter_manager.json │ │ │ │ ├── orange_crafting_grid.json │ │ │ │ ├── orange_crafting_monitor.json │ │ │ │ ├── orange_detector.json │ │ │ │ ├── orange_disk_manipulator.json │ │ │ │ ├── orange_fluid_grid.json │ │ │ │ ├── orange_grid.json │ │ │ │ ├── orange_network_receiver.json │ │ │ │ ├── orange_network_transmitter.json │ │ │ │ ├── orange_pattern_grid.json │ │ │ │ ├── orange_relay.json │ │ │ │ ├── orange_security_manager.json │ │ │ │ ├── orange_wireless_transmitter.json │ │ │ │ ├── pattern_grid.json │ │ │ │ ├── pink_controller.json │ │ │ │ ├── pink_crafter.json │ │ │ │ ├── pink_crafter_manager.json │ │ │ │ ├── pink_crafting_grid.json │ │ │ │ ├── pink_crafting_monitor.json │ │ │ │ ├── pink_detector.json │ │ │ │ ├── pink_disk_manipulator.json │ │ │ │ ├── pink_fluid_grid.json │ │ │ │ ├── pink_grid.json │ │ │ │ ├── pink_network_receiver.json │ │ │ │ ├── pink_network_transmitter.json │ │ │ │ ├── pink_pattern_grid.json │ │ │ │ ├── pink_relay.json │ │ │ │ ├── pink_security_manager.json │ │ │ │ ├── pink_wireless_transmitter.json │ │ │ │ ├── purple_controller.json │ │ │ │ ├── purple_crafter.json │ │ │ │ ├── purple_crafter_manager.json │ │ │ │ ├── purple_crafting_grid.json │ │ │ │ ├── purple_crafting_monitor.json │ │ │ │ ├── purple_detector.json │ │ │ │ ├── purple_disk_manipulator.json │ │ │ │ ├── purple_fluid_grid.json │ │ │ │ ├── purple_grid.json │ │ │ │ ├── purple_network_receiver.json │ │ │ │ ├── purple_network_transmitter.json │ │ │ │ ├── purple_pattern_grid.json │ │ │ │ ├── purple_relay.json │ │ │ │ ├── purple_security_manager.json │ │ │ │ ├── purple_wireless_transmitter.json │ │ │ │ ├── red_controller.json │ │ │ │ ├── red_crafter.json │ │ │ │ ├── red_crafter_manager.json │ │ │ │ ├── red_crafting_grid.json │ │ │ │ ├── red_crafting_monitor.json │ │ │ │ ├── red_detector.json │ │ │ │ ├── red_disk_manipulator.json │ │ │ │ ├── red_fluid_grid.json │ │ │ │ ├── red_grid.json │ │ │ │ ├── red_network_receiver.json │ │ │ │ ├── red_network_transmitter.json │ │ │ │ ├── red_pattern_grid.json │ │ │ │ ├── red_relay.json │ │ │ │ ├── red_security_manager.json │ │ │ │ ├── red_wireless_transmitter.json │ │ │ │ ├── relay.json │ │ │ │ ├── security_manager.json │ │ │ │ ├── white_controller.json │ │ │ │ ├── white_crafter.json │ │ │ │ ├── white_crafter_manager.json │ │ │ │ ├── white_crafting_grid.json │ │ │ │ ├── white_crafting_monitor.json │ │ │ │ ├── white_detector.json │ │ │ │ ├── white_disk_manipulator.json │ │ │ │ ├── white_fluid_grid.json │ │ │ │ ├── white_grid.json │ │ │ │ ├── white_network_receiver.json │ │ │ │ ├── white_network_transmitter.json │ │ │ │ ├── white_pattern_grid.json │ │ │ │ ├── white_relay.json │ │ │ │ ├── white_security_manager.json │ │ │ │ ├── white_wireless_transmitter.json │ │ │ │ ├── wireless_transmitter.json │ │ │ │ ├── yellow_controller.json │ │ │ │ ├── yellow_crafter.json │ │ │ │ ├── yellow_crafter_manager.json │ │ │ │ ├── yellow_crafting_grid.json │ │ │ │ ├── yellow_crafting_monitor.json │ │ │ │ ├── yellow_detector.json │ │ │ │ ├── yellow_disk_manipulator.json │ │ │ │ ├── yellow_fluid_grid.json │ │ │ │ ├── yellow_grid.json │ │ │ │ ├── yellow_network_receiver.json │ │ │ │ ├── yellow_network_transmitter.json │ │ │ │ ├── yellow_pattern_grid.json │ │ │ │ ├── yellow_relay.json │ │ │ │ ├── yellow_security_manager.json │ │ │ │ └── yellow_wireless_transmitter.json │ │ │ ├── crafting_grid/ │ │ │ │ ├── black_crafting_grid.json │ │ │ │ ├── blue_crafting_grid.json │ │ │ │ ├── brown_crafting_grid.json │ │ │ │ ├── crafting_grid.json │ │ │ │ ├── cyan_crafting_grid.json │ │ │ │ ├── gray_crafting_grid.json │ │ │ │ ├── green_crafting_grid.json │ │ │ │ ├── light_gray_crafting_grid.json │ │ │ │ ├── lime_crafting_grid.json │ │ │ │ ├── magenta_crafting_grid.json │ │ │ │ ├── orange_crafting_grid.json │ │ │ │ ├── pink_crafting_grid.json │ │ │ │ ├── purple_crafting_grid.json │ │ │ │ ├── red_crafting_grid.json │ │ │ │ ├── white_crafting_grid.json │ │ │ │ └── yellow_crafting_grid.json │ │ │ ├── fluid_grid/ │ │ │ │ ├── black_fluid_grid.json │ │ │ │ ├── blue_fluid_grid.json │ │ │ │ ├── brown_fluid_grid.json │ │ │ │ ├── cyan_fluid_grid.json │ │ │ │ ├── fluid_grid.json │ │ │ │ ├── gray_fluid_grid.json │ │ │ │ ├── green_fluid_grid.json │ │ │ │ ├── light_gray_fluid_grid.json │ │ │ │ ├── lime_fluid_grid.json │ │ │ │ ├── magenta_fluid_grid.json │ │ │ │ ├── orange_fluid_grid.json │ │ │ │ ├── pink_fluid_grid.json │ │ │ │ ├── purple_fluid_grid.json │ │ │ │ ├── red_fluid_grid.json │ │ │ │ ├── white_fluid_grid.json │ │ │ │ └── yellow_fluid_grid.json │ │ │ └── pattern_grid/ │ │ │ ├── black_pattern_grid.json │ │ │ ├── blue_pattern_grid.json │ │ │ ├── brown_pattern_grid.json │ │ │ ├── cyan_pattern_grid.json │ │ │ ├── gray_pattern_grid.json │ │ │ ├── green_pattern_grid.json │ │ │ ├── light_gray_pattern_grid.json │ │ │ ├── lime_pattern_grid.json │ │ │ ├── magenta_pattern_grid.json │ │ │ ├── orange_pattern_grid.json │ │ │ ├── pattern_grid.json │ │ │ ├── pink_pattern_grid.json │ │ │ ├── purple_pattern_grid.json │ │ │ ├── red_pattern_grid.json │ │ │ ├── white_pattern_grid.json │ │ │ └── yellow_pattern_grid.json │ │ └── tags/ │ │ ├── blocks/ │ │ │ ├── controller.json │ │ │ ├── crafter.json │ │ │ ├── crafter_manager.json │ │ │ ├── crafting_grid.json │ │ │ ├── crafting_monitor.json │ │ │ ├── creative_controller.json │ │ │ ├── detector.json │ │ │ ├── disk_manipulator.json │ │ │ ├── fluid_grid.json │ │ │ ├── grid.json │ │ │ ├── network_receiver.json │ │ │ ├── network_transmitter.json │ │ │ ├── pattern_grid.json │ │ │ ├── relay.json │ │ │ ├── security_manager.json │ │ │ └── wireless_transmitter.json │ │ └── items/ │ │ ├── controller.json │ │ ├── crafter.json │ │ ├── crafter_manager.json │ │ ├── crafting_grid.json │ │ ├── crafting_monitor.json │ │ ├── detector.json │ │ ├── disk_manipulator.json │ │ ├── fluid_grid.json │ │ ├── grid.json │ │ ├── network_receiver.json │ │ ├── network_transmitter.json │ │ ├── pattern_grid.json │ │ ├── relay.json │ │ ├── security_manager.json │ │ └── wireless_transmitter.json │ └── main/ │ ├── java/ │ │ └── com/ │ │ └── refinedmods/ │ │ └── refinedstorage/ │ │ ├── RS.java │ │ ├── RSBlockEntities.java │ │ ├── RSBlocks.java │ │ ├── RSContainerMenus.java │ │ ├── RSCreativeModeTabItems.java │ │ ├── RSItems.java │ │ ├── RSKeyBindings.java │ │ ├── RSLootFunctions.java │ │ ├── RSRecipeSerializers.java │ │ ├── api/ │ │ │ ├── IRSAPI.java │ │ │ ├── RSAPIInject.java │ │ │ ├── autocrafting/ │ │ │ │ ├── ICraftingManager.java │ │ │ │ ├── ICraftingPattern.java │ │ │ │ ├── ICraftingPatternContainer.java │ │ │ │ ├── ICraftingPatternProvider.java │ │ │ │ ├── ICraftingPatternRenderHandler.java │ │ │ │ ├── craftingmonitor/ │ │ │ │ │ ├── ICraftingMonitorElement.java │ │ │ │ │ ├── ICraftingMonitorElementList.java │ │ │ │ │ ├── ICraftingMonitorElementRegistry.java │ │ │ │ │ └── ICraftingMonitorListener.java │ │ │ │ ├── preview/ │ │ │ │ │ ├── ICraftingPreviewElement.java │ │ │ │ │ └── ICraftingPreviewElementRegistry.java │ │ │ │ └── task/ │ │ │ │ ├── CalculationResultType.java │ │ │ │ ├── CraftingTaskReadException.java │ │ │ │ ├── ICalculationResult.java │ │ │ │ ├── ICraftingRequestInfo.java │ │ │ │ ├── ICraftingTask.java │ │ │ │ ├── ICraftingTaskFactory.java │ │ │ │ └── ICraftingTaskRegistry.java │ │ │ ├── network/ │ │ │ │ ├── INetwork.java │ │ │ │ ├── INetworkManager.java │ │ │ │ ├── INetworkNodeGraph.java │ │ │ │ ├── INetworkNodeGraphEntry.java │ │ │ │ ├── INetworkNodeGraphListener.java │ │ │ │ ├── INetworkNodeVisitor.java │ │ │ │ ├── IWirelessTransmitter.java │ │ │ │ ├── NetworkType.java │ │ │ │ ├── grid/ │ │ │ │ │ ├── GridFactoryType.java │ │ │ │ │ ├── GridType.java │ │ │ │ │ ├── ICraftingGridBehavior.java │ │ │ │ │ ├── ICraftingGridListener.java │ │ │ │ │ ├── IGrid.java │ │ │ │ │ ├── IGridFactory.java │ │ │ │ │ ├── IGridManager.java │ │ │ │ │ ├── IGridTab.java │ │ │ │ │ ├── INetworkAwareGrid.java │ │ │ │ │ └── handler/ │ │ │ │ │ ├── IFluidGridHandler.java │ │ │ │ │ └── IItemGridHandler.java │ │ │ │ ├── item/ │ │ │ │ │ ├── INetworkItem.java │ │ │ │ │ ├── INetworkItemManager.java │ │ │ │ │ └── INetworkItemProvider.java │ │ │ │ ├── node/ │ │ │ │ │ ├── ICoverable.java │ │ │ │ │ ├── INetworkNode.java │ │ │ │ │ ├── INetworkNodeFactory.java │ │ │ │ │ ├── INetworkNodeManager.java │ │ │ │ │ ├── INetworkNodeProxy.java │ │ │ │ │ └── INetworkNodeRegistry.java │ │ │ │ └── security/ │ │ │ │ ├── ISecurityCard.java │ │ │ │ ├── ISecurityCardContainer.java │ │ │ │ ├── ISecurityManager.java │ │ │ │ └── Permission.java │ │ │ ├── render/ │ │ │ │ ├── IElementDrawer.java │ │ │ │ └── IElementDrawers.java │ │ │ ├── storage/ │ │ │ │ ├── AccessType.java │ │ │ │ ├── IStorage.java │ │ │ │ ├── IStorageProvider.java │ │ │ │ ├── StorageType.java │ │ │ │ ├── cache/ │ │ │ │ │ ├── IStorageCache.java │ │ │ │ │ ├── IStorageCacheListener.java │ │ │ │ │ └── InvalidateCause.java │ │ │ │ ├── disk/ │ │ │ │ │ ├── IStorageDisk.java │ │ │ │ │ ├── IStorageDiskContainerContext.java │ │ │ │ │ ├── IStorageDiskFactory.java │ │ │ │ │ ├── IStorageDiskListener.java │ │ │ │ │ ├── IStorageDiskManager.java │ │ │ │ │ ├── IStorageDiskProvider.java │ │ │ │ │ ├── IStorageDiskRegistry.java │ │ │ │ │ ├── IStorageDiskSync.java │ │ │ │ │ └── StorageDiskSyncData.java │ │ │ │ ├── externalstorage/ │ │ │ │ │ ├── IExternalStorage.java │ │ │ │ │ ├── IExternalStorageContext.java │ │ │ │ │ └── IExternalStorageProvider.java │ │ │ │ └── tracker/ │ │ │ │ ├── IStorageTracker.java │ │ │ │ ├── IStorageTrackerManager.java │ │ │ │ └── StorageTrackerEntry.java │ │ │ └── util/ │ │ │ ├── Action.java │ │ │ ├── IComparer.java │ │ │ ├── IFilter.java │ │ │ ├── IQuantityFormatter.java │ │ │ ├── IStackList.java │ │ │ ├── StackListEntry.java │ │ │ └── StackListResult.java │ │ ├── apiimpl/ │ │ │ ├── API.java │ │ │ ├── autocrafting/ │ │ │ │ ├── AllowedTagList.java │ │ │ │ ├── CraftingManager.java │ │ │ │ ├── CraftingPattern.java │ │ │ │ ├── CraftingPatternContext.java │ │ │ │ ├── CraftingPatternFactory.java │ │ │ │ ├── CraftingPatternFactoryException.java │ │ │ │ ├── CraftingPatternInputs.java │ │ │ │ ├── CraftingPatternOutputs.java │ │ │ │ ├── InvalidCraftingPattern.java │ │ │ │ ├── craftingmonitor/ │ │ │ │ │ ├── CraftingMonitorElementList.java │ │ │ │ │ ├── CraftingMonitorElementRegistry.java │ │ │ │ │ ├── ErrorCraftingMonitorElement.java │ │ │ │ │ ├── FluidCraftingMonitorElement.java │ │ │ │ │ └── ItemCraftingMonitorElement.java │ │ │ │ ├── preview/ │ │ │ │ │ ├── CraftingPreviewElementRegistry.java │ │ │ │ │ ├── ErrorCraftingPreviewElement.java │ │ │ │ │ ├── FluidCraftingPreviewElement.java │ │ │ │ │ └── ItemCraftingPreviewElement.java │ │ │ │ └── task/ │ │ │ │ ├── CraftingRequestInfo.java │ │ │ │ ├── CraftingTaskRegistry.java │ │ │ │ ├── README.md │ │ │ │ └── v6/ │ │ │ │ ├── CraftingPatternInputs.java │ │ │ │ ├── CraftingTask.java │ │ │ │ ├── CraftingTaskFactory.java │ │ │ │ ├── IoUtil.java │ │ │ │ ├── SerializationUtil.java │ │ │ │ ├── calculator/ │ │ │ │ │ ├── CalculationResult.java │ │ │ │ │ ├── CraftingCalculator.java │ │ │ │ │ ├── CraftingCalculatorException.java │ │ │ │ │ └── PossibleInputs.java │ │ │ │ ├── monitor/ │ │ │ │ │ └── CraftingMonitorElementFactory.java │ │ │ │ ├── node/ │ │ │ │ │ ├── CraftingNode.java │ │ │ │ │ ├── Node.java │ │ │ │ │ ├── NodeList.java │ │ │ │ │ ├── NodeListener.java │ │ │ │ │ ├── NodeRequirements.java │ │ │ │ │ ├── ProcessingNode.java │ │ │ │ │ └── ProcessingState.java │ │ │ │ └── preview/ │ │ │ │ ├── CraftingPreviewElementFactory.java │ │ │ │ └── CraftingPreviewInfo.java │ │ │ ├── network/ │ │ │ │ ├── Network.java │ │ │ │ ├── NetworkListener.java │ │ │ │ ├── NetworkManager.java │ │ │ │ ├── NetworkNodeGraph.java │ │ │ │ ├── NetworkNodeGraphEntry.java │ │ │ │ ├── NetworkNodeListener.java │ │ │ │ ├── NetworkNodeManager.java │ │ │ │ ├── NetworkNodeRegistry.java │ │ │ │ ├── grid/ │ │ │ │ │ ├── CraftingGridBehavior.java │ │ │ │ │ ├── GridManager.java │ │ │ │ │ ├── GridTab.java │ │ │ │ │ ├── factory/ │ │ │ │ │ │ ├── GridBlockGridFactory.java │ │ │ │ │ │ ├── PortableGridBlockGridFactory.java │ │ │ │ │ │ ├── PortableGridGridFactory.java │ │ │ │ │ │ ├── WirelessFluidGridGridFactory.java │ │ │ │ │ │ └── WirelessGridGridFactory.java │ │ │ │ │ └── handler/ │ │ │ │ │ ├── FluidGridHandler.java │ │ │ │ │ ├── ItemGridHandler.java │ │ │ │ │ ├── PortableFluidGridHandler.java │ │ │ │ │ └── PortableItemGridHandler.java │ │ │ │ ├── item/ │ │ │ │ │ ├── NetworkItemManager.java │ │ │ │ │ ├── WirelessCraftingMonitorNetworkItem.java │ │ │ │ │ ├── WirelessFluidGridNetworkItem.java │ │ │ │ │ └── WirelessGridNetworkItem.java │ │ │ │ ├── node/ │ │ │ │ │ ├── CableNetworkNode.java │ │ │ │ │ ├── ConnectivityStateChangeCause.java │ │ │ │ │ ├── ConstructorNetworkNode.java │ │ │ │ │ ├── CrafterManagerNetworkNode.java │ │ │ │ │ ├── CrafterNetworkNode.java │ │ │ │ │ ├── CraftingMonitorNetworkNode.java │ │ │ │ │ ├── DestructorNetworkNode.java │ │ │ │ │ ├── DetectorNetworkNode.java │ │ │ │ │ ├── DiskState.java │ │ │ │ │ ├── ExporterNetworkNode.java │ │ │ │ │ ├── ExternalStorageNetworkNode.java │ │ │ │ │ ├── FluidInterfaceNetworkNode.java │ │ │ │ │ ├── GridNetworkNode.java │ │ │ │ │ ├── IStorageScreen.java │ │ │ │ │ ├── ImporterNetworkNode.java │ │ │ │ │ ├── InterfaceNetworkNode.java │ │ │ │ │ ├── NetworkNode.java │ │ │ │ │ ├── NetworkReceiverNetworkNode.java │ │ │ │ │ ├── NetworkTransmitterNetworkNode.java │ │ │ │ │ ├── RelayNetworkNode.java │ │ │ │ │ ├── RootNetworkNode.java │ │ │ │ │ ├── SecurityManagerNetworkNode.java │ │ │ │ │ ├── SlottedCraftingRequest.java │ │ │ │ │ ├── StorageMonitorNetworkNode.java │ │ │ │ │ ├── WirelessTransmitterNetworkNode.java │ │ │ │ │ ├── cover/ │ │ │ │ │ │ ├── Cover.java │ │ │ │ │ │ ├── CoverManager.java │ │ │ │ │ │ └── CoverType.java │ │ │ │ │ ├── diskdrive/ │ │ │ │ │ │ ├── DiskDriveNetworkNode.java │ │ │ │ │ │ ├── FluidDriveWrapperStorageDisk.java │ │ │ │ │ │ └── ItemDriveWrapperStorageDisk.java │ │ │ │ │ ├── diskmanipulator/ │ │ │ │ │ │ ├── DiskManipulatorNetworkNode.java │ │ │ │ │ │ ├── StorageDiskFluidManipulatorWrapper.java │ │ │ │ │ │ └── StorageDiskItemManipulatorWrapper.java │ │ │ │ │ └── storage/ │ │ │ │ │ ├── FluidStorageNetworkNode.java │ │ │ │ │ ├── FluidStorageWrapperStorageDisk.java │ │ │ │ │ ├── ItemStorageWrapperStorageDisk.java │ │ │ │ │ └── StorageNetworkNode.java │ │ │ │ └── security/ │ │ │ │ ├── SecurityCard.java │ │ │ │ └── SecurityManager.java │ │ │ ├── render/ │ │ │ │ ├── CraftingMonitorElementDrawers.java │ │ │ │ ├── CraftingPreviewElementDrawers.java │ │ │ │ └── ElementDrawers.java │ │ │ ├── storage/ │ │ │ │ ├── FluidStorageType.java │ │ │ │ ├── ItemStorageType.java │ │ │ │ ├── cache/ │ │ │ │ │ ├── FluidStorageCache.java │ │ │ │ │ ├── ItemStorageCache.java │ │ │ │ │ ├── PortableFluidStorageCache.java │ │ │ │ │ ├── PortableItemStorageCache.java │ │ │ │ │ └── listener/ │ │ │ │ │ ├── FluidGridStorageCacheListener.java │ │ │ │ │ ├── ItemGridStorageCacheListener.java │ │ │ │ │ ├── PortableFluidGridStorageCacheListener.java │ │ │ │ │ └── PortableItemGridStorageCacheListener.java │ │ │ │ ├── disk/ │ │ │ │ │ ├── FluidStorageDisk.java │ │ │ │ │ ├── ItemStorageDisk.java │ │ │ │ │ ├── PortableFluidStorageDisk.java │ │ │ │ │ ├── PortableItemStorageDisk.java │ │ │ │ │ ├── StorageDiskManager.java │ │ │ │ │ ├── StorageDiskRegistry.java │ │ │ │ │ ├── StorageDiskSync.java │ │ │ │ │ └── factory/ │ │ │ │ │ ├── FluidStorageDiskFactory.java │ │ │ │ │ └── ItemStorageDiskFactory.java │ │ │ │ ├── externalstorage/ │ │ │ │ │ ├── FluidExternalStorage.java │ │ │ │ │ ├── FluidExternalStorageCache.java │ │ │ │ │ ├── FluidExternalStorageProvider.java │ │ │ │ │ ├── ItemExternalStorage.java │ │ │ │ │ ├── ItemExternalStorageCache.java │ │ │ │ │ └── ItemExternalStorageProvider.java │ │ │ │ └── tracker/ │ │ │ │ ├── FluidStorageTracker.java │ │ │ │ ├── ItemStorageTracker.java │ │ │ │ └── StorageTrackerManager.java │ │ │ └── util/ │ │ │ ├── Comparer.java │ │ │ ├── FluidFilter.java │ │ │ ├── FluidStackList.java │ │ │ ├── ItemFilter.java │ │ │ ├── ItemStackList.java │ │ │ ├── QuantityFormatter.java │ │ │ └── RSSavedData.java │ │ ├── block/ │ │ │ ├── BaseBlock.java │ │ │ ├── BlockDirection.java │ │ │ ├── BlockListener.java │ │ │ ├── CableBlock.java │ │ │ ├── ColoredNetworkBlock.java │ │ │ ├── ConstructorBlock.java │ │ │ ├── ControllerBlock.java │ │ │ ├── CrafterBlock.java │ │ │ ├── CrafterManagerBlock.java │ │ │ ├── CraftingMonitorBlock.java │ │ │ ├── DestructorBlock.java │ │ │ ├── DetectorBlock.java │ │ │ ├── DiskDriveBlock.java │ │ │ ├── DiskManipulatorBlock.java │ │ │ ├── ExporterBlock.java │ │ │ ├── ExternalStorageBlock.java │ │ │ ├── FluidInterfaceBlock.java │ │ │ ├── FluidStorageBlock.java │ │ │ ├── GridBlock.java │ │ │ ├── ImporterBlock.java │ │ │ ├── InterfaceBlock.java │ │ │ ├── MachineCasingBlock.java │ │ │ ├── NetworkNodeBlock.java │ │ │ ├── NetworkReceiverBlock.java │ │ │ ├── NetworkTransmitterBlock.java │ │ │ ├── PortableGridBlock.java │ │ │ ├── QuartzEnrichedIronBlock.java │ │ │ ├── RelayBlock.java │ │ │ ├── SecurityManagerBlock.java │ │ │ ├── StorageBlock.java │ │ │ ├── StorageMonitorBlock.java │ │ │ ├── WirelessTransmitterBlock.java │ │ │ └── shape/ │ │ │ └── ShapeCache.java │ │ ├── blockentity/ │ │ │ ├── BaseBlockEntity.java │ │ │ ├── CableBlockEntity.java │ │ │ ├── ClientNode.java │ │ │ ├── ConstructorBlockEntity.java │ │ │ ├── ControllerBlockEntity.java │ │ │ ├── CrafterBlockEntity.java │ │ │ ├── CrafterManagerBlockEntity.java │ │ │ ├── DestructorBlockEntity.java │ │ │ ├── DetectorBlockEntity.java │ │ │ ├── DiskDriveBlockEntity.java │ │ │ ├── DiskManipulatorBlockEntity.java │ │ │ ├── ExporterBlockEntity.java │ │ │ ├── ExternalStorageBlockEntity.java │ │ │ ├── FluidInterfaceBlockEntity.java │ │ │ ├── FluidStorageBlockEntity.java │ │ │ ├── ImporterBlockEntity.java │ │ │ ├── InterfaceBlockEntity.java │ │ │ ├── NetworkNodeBlockEntity.java │ │ │ ├── NetworkReceiverBlockEntity.java │ │ │ ├── NetworkTransmitterBlockEntity.java │ │ │ ├── RelayBlockEntity.java │ │ │ ├── SecurityManagerBlockEntity.java │ │ │ ├── StorageBlockEntity.java │ │ │ ├── StorageMonitorBlockEntity.java │ │ │ ├── WirelessTransmitterBlockEntity.java │ │ │ ├── config/ │ │ │ │ ├── IAccessType.java │ │ │ │ ├── IComparable.java │ │ │ │ ├── IPrioritizable.java │ │ │ │ ├── IRedstoneConfigurable.java │ │ │ │ ├── IType.java │ │ │ │ ├── IWhitelistBlacklist.java │ │ │ │ └── RedstoneMode.java │ │ │ ├── craftingmonitor/ │ │ │ │ ├── CraftingMonitorBlockEntity.java │ │ │ │ ├── ICraftingMonitor.java │ │ │ │ └── WirelessCraftingMonitor.java │ │ │ ├── data/ │ │ │ │ ├── BlockEntitySynchronizationClientListener.java │ │ │ │ ├── BlockEntitySynchronizationManager.java │ │ │ │ ├── BlockEntitySynchronizationParameter.java │ │ │ │ ├── BlockEntitySynchronizationSpec.java │ │ │ │ ├── BlockEntitySynchronizationWatcher.java │ │ │ │ └── RSSerializers.java │ │ │ └── grid/ │ │ │ ├── GridBlockEntity.java │ │ │ ├── WirelessFluidGrid.java │ │ │ ├── WirelessGrid.java │ │ │ └── portable/ │ │ │ ├── IPortableGrid.java │ │ │ ├── PortableGrid.java │ │ │ ├── PortableGridBlockEntity.java │ │ │ └── PortableGridDiskState.java │ │ ├── command/ │ │ │ ├── disk/ │ │ │ │ ├── CreateDiskCommand.java │ │ │ │ ├── ListDiskCommand.java │ │ │ │ ├── ListDiskForPlayerCommand.java │ │ │ │ └── StorageDiskIdSuggestionProvider.java │ │ │ ├── network/ │ │ │ │ ├── GetNetworkCommand.java │ │ │ │ ├── ListNetworkCommand.java │ │ │ │ ├── NetworkCommand.java │ │ │ │ ├── NetworkPositionSuggestionProvider.java │ │ │ │ └── autocrafting/ │ │ │ │ ├── AutocraftingIdSuggestionProvider.java │ │ │ │ ├── CancelAllAutocraftingCommand.java │ │ │ │ ├── CancelSingleAutocraftingCommand.java │ │ │ │ ├── GetAutocraftingCommand.java │ │ │ │ └── ListAutocraftingCommand.java │ │ │ └── pattern/ │ │ │ └── PatternDumpCommand.java │ │ ├── config/ │ │ │ ├── ClientConfig.java │ │ │ └── ServerConfig.java │ │ ├── container/ │ │ │ ├── AlternativesContainerMenu.java │ │ │ ├── AmountContainerMenu.java │ │ │ ├── BaseContainerMenu.java │ │ │ ├── ConstructorContainerMenu.java │ │ │ ├── ControllerContainerMenu.java │ │ │ ├── CrafterContainerMenu.java │ │ │ ├── CrafterManagerContainerMenu.java │ │ │ ├── CraftingMonitorContainerMenu.java │ │ │ ├── CraftingSettingsContainerMenu.java │ │ │ ├── DestructorContainerMenu.java │ │ │ ├── DetectorContainerMenu.java │ │ │ ├── DiskDriveContainerMenu.java │ │ │ ├── DiskManipulatorContainerMenu.java │ │ │ ├── ExporterContainerMenu.java │ │ │ ├── ExternalStorageContainerMenu.java │ │ │ ├── FilterContainerMenu.java │ │ │ ├── FluidAmountContainerMenu.java │ │ │ ├── FluidInterfaceContainerMenu.java │ │ │ ├── FluidStorageContainerMenu.java │ │ │ ├── GridContainerMenu.java │ │ │ ├── ImporterContainerMenu.java │ │ │ ├── InterfaceContainerMenu.java │ │ │ ├── NetworkTransmitterContainerMenu.java │ │ │ ├── RelayContainerMenu.java │ │ │ ├── SecurityManagerContainerMenu.java │ │ │ ├── StorageContainerMenu.java │ │ │ ├── StorageMonitorContainerMenu.java │ │ │ ├── WirelessTransmitterContainerMenu.java │ │ │ ├── factory/ │ │ │ │ ├── BlockEntityContainerFactory.java │ │ │ │ ├── BlockEntityMenuProvider.java │ │ │ │ ├── CrafterManagerContainerFactory.java │ │ │ │ ├── CrafterManagerMenuProvider.java │ │ │ │ ├── CraftingMonitorContainerFactory.java │ │ │ │ ├── CraftingMonitorMenuProvider.java │ │ │ │ ├── GridContainerFactory.java │ │ │ │ ├── GridMenuProvider.java │ │ │ │ └── WirelessCraftingMonitorContainerFactory.java │ │ │ ├── slot/ │ │ │ │ ├── BaseSlot.java │ │ │ │ ├── CrafterManagerSlot.java │ │ │ │ ├── DisabledSlot.java │ │ │ │ ├── OutputSlot.java │ │ │ │ ├── filter/ │ │ │ │ │ ├── DisabledFluidFilterSlot.java │ │ │ │ │ ├── FilterSlot.java │ │ │ │ │ └── FluidFilterSlot.java │ │ │ │ ├── grid/ │ │ │ │ │ ├── CraftingGridSlot.java │ │ │ │ │ └── ResultCraftingGridSlot.java │ │ │ │ └── legacy/ │ │ │ │ ├── LegacyBaseSlot.java │ │ │ │ ├── LegacyDisabledSlot.java │ │ │ │ └── LegacyFilterSlot.java │ │ │ └── transfer/ │ │ │ ├── FilterInventoryWrapper.java │ │ │ ├── FluidFilterInventoryWrapper.java │ │ │ ├── IInventoryWrapper.java │ │ │ ├── InsertionResult.java │ │ │ ├── InsertionResultType.java │ │ │ ├── InventoryInventoryWrapper.java │ │ │ ├── ItemFilterInventoryWrapper.java │ │ │ ├── ItemHandlerInventoryWrapper.java │ │ │ └── TransferManager.java │ │ ├── datageneration/ │ │ │ ├── BlockEntityTagGenerator.java │ │ │ ├── BlockModelGenerator.java │ │ │ ├── BlockModels.java │ │ │ ├── BlockTagGenerator.java │ │ │ ├── DataGenerators.java │ │ │ ├── ItemTagGenerator.java │ │ │ ├── LootTableGenerator.java │ │ │ └── RecipeGenerator.java │ │ ├── energy/ │ │ │ ├── BaseEnergyStorage.java │ │ │ └── ItemEnergyStorage.java │ │ ├── integration/ │ │ │ ├── craftingtweaks/ │ │ │ │ └── CraftingTweaksIntegration.java │ │ │ ├── curios/ │ │ │ │ └── CuriosIntegration.java │ │ │ ├── inventorysorter/ │ │ │ │ └── InventorySorterIntegration.java │ │ │ ├── inventorytweaks/ │ │ │ │ └── InventoryTweaksIntegration.java │ │ │ └── jei/ │ │ │ ├── CoverCraftingCategoryExtension.java │ │ │ ├── GhostIngredientHandler.java │ │ │ ├── GridRecipeTransferHandler.java │ │ │ ├── GuiContainerHandler.java │ │ │ ├── HollowCoverCraftingCategoryExtension.java │ │ │ ├── Ingredient.java │ │ │ ├── IngredientTracker.java │ │ │ ├── JeiHelper.java │ │ │ ├── JeiIntegration.java │ │ │ ├── RSJeiPlugin.java │ │ │ ├── RecipeTransferCraftingGridError.java │ │ │ └── RecipeTransferPatternGridError.java │ │ ├── inventory/ │ │ │ ├── fluid/ │ │ │ │ ├── ConfiguredFluidsInFilterItemHandler.java │ │ │ │ ├── ConfiguredIconInFluidFilterItemHandler.java │ │ │ │ ├── FluidInventory.java │ │ │ │ └── ProxyFluidHandler.java │ │ │ ├── item/ │ │ │ │ ├── BaseItemHandler.java │ │ │ │ ├── ConfiguredIconInFilterItemHandler.java │ │ │ │ ├── ConfiguredItemsInFilterItemHandler.java │ │ │ │ ├── FilterItemHandler.java │ │ │ │ ├── ProxyItemHandler.java │ │ │ │ ├── UpgradeItemHandler.java │ │ │ │ └── validator/ │ │ │ │ ├── ItemValidator.java │ │ │ │ ├── PatternItemValidator.java │ │ │ │ ├── StorageDiskItemValidator.java │ │ │ │ └── UpgradeItemValidator.java │ │ │ ├── listener/ │ │ │ │ ├── BlockEntityInventoryListener.java │ │ │ │ ├── InventoryListener.java │ │ │ │ ├── NetworkNodeFluidInventoryListener.java │ │ │ │ └── NetworkNodeInventoryListener.java │ │ │ └── player/ │ │ │ └── PlayerSlot.java │ │ ├── item/ │ │ │ ├── CoreItem.java │ │ │ ├── CoverItem.java │ │ │ ├── EnergyItem.java │ │ │ ├── FilterItem.java │ │ │ ├── FluidStorageDiskItem.java │ │ │ ├── FluidStoragePartItem.java │ │ │ ├── HollowCoverItem.java │ │ │ ├── NetworkCardItem.java │ │ │ ├── NetworkItem.java │ │ │ ├── PatternItem.java │ │ │ ├── ProcessorBindingItem.java │ │ │ ├── ProcessorItem.java │ │ │ ├── QuartzEnrichedIronItem.java │ │ │ ├── SecurityCardItem.java │ │ │ ├── SiliconItem.java │ │ │ ├── StorageDiskItem.java │ │ │ ├── StorageHousingItem.java │ │ │ ├── StoragePartItem.java │ │ │ ├── UpgradeItem.java │ │ │ ├── WirelessCraftingMonitorItem.java │ │ │ ├── WirelessFluidGridItem.java │ │ │ ├── WirelessGridItem.java │ │ │ ├── WrenchItem.java │ │ │ ├── blockitem/ │ │ │ │ ├── BaseBlockItem.java │ │ │ │ ├── ColoredBlockItem.java │ │ │ │ ├── ControllerBlockItem.java │ │ │ │ ├── EnergyBlockItem.java │ │ │ │ ├── FluidStorageBlockItem.java │ │ │ │ ├── PortableGridBlockItem.java │ │ │ │ └── StorageBlockItem.java │ │ │ └── property/ │ │ │ ├── ControllerItemPropertyGetter.java │ │ │ ├── NetworkItemPropertyGetter.java │ │ │ └── SecurityCardItemPropertyGetter.java │ │ ├── loottable/ │ │ │ ├── ControllerLootFunction.java │ │ │ ├── CrafterLootFunction.java │ │ │ ├── PortableGridBlockLootFunction.java │ │ │ └── StorageBlockLootFunction.java │ │ ├── network/ │ │ │ ├── ClientProxy.java │ │ │ ├── FilterUpdateMessage.java │ │ │ ├── FluidFilterSlotUpdateMessage.java │ │ │ ├── NetworkHandler.java │ │ │ ├── OpenNetworkItemMessage.java │ │ │ ├── SecurityManagerUpdateMessage.java │ │ │ ├── SetFilterSlotMessage.java │ │ │ ├── SetFluidFilterSlotMessage.java │ │ │ ├── craftingmonitor/ │ │ │ │ ├── CraftingMonitorCancelMessage.java │ │ │ │ ├── CraftingMonitorSyncTask.java │ │ │ │ ├── CraftingMonitorUpdateMessage.java │ │ │ │ └── WirelessCraftingMonitorSettingsUpdateMessage.java │ │ │ ├── disk/ │ │ │ │ ├── StorageDiskSizeRequestMessage.java │ │ │ │ └── StorageDiskSizeResponseMessage.java │ │ │ ├── grid/ │ │ │ │ ├── GridClearMessage.java │ │ │ │ ├── GridCraftingPreviewRequestMessage.java │ │ │ │ ├── GridCraftingPreviewResponseMessage.java │ │ │ │ ├── GridCraftingStartRequestMessage.java │ │ │ │ ├── GridCraftingStartResponseMessage.java │ │ │ │ ├── GridFluidDeltaMessage.java │ │ │ │ ├── GridFluidInsertHeldMessage.java │ │ │ │ ├── GridFluidPullMessage.java │ │ │ │ ├── GridFluidUpdateMessage.java │ │ │ │ ├── GridItemDeltaMessage.java │ │ │ │ ├── GridItemGridScrollMessage.java │ │ │ │ ├── GridItemInsertHeldMessage.java │ │ │ │ ├── GridItemInventoryScrollMessage.java │ │ │ │ ├── GridItemPullMessage.java │ │ │ │ ├── GridItemUpdateMessage.java │ │ │ │ ├── GridPatternCreateMessage.java │ │ │ │ ├── GridProcessingTransferMessage.java │ │ │ │ ├── GridStackDelta.java │ │ │ │ ├── GridTransferMessage.java │ │ │ │ ├── PortableGridSettingsUpdateMessage.java │ │ │ │ ├── WirelessFluidGridSettingsUpdateMessage.java │ │ │ │ └── WirelessGridSettingsUpdateMessage.java │ │ │ └── sync/ │ │ │ ├── BlockEntitySynchronizationParameterMessage.java │ │ │ └── BlockEntitySynchronizationParameterUpdateMessage.java │ │ ├── recipe/ │ │ │ ├── CoverRecipe.java │ │ │ ├── HollowCoverRecipe.java │ │ │ ├── UpgradeWithEnchantedBookRecipe.java │ │ │ └── UpgradeWithEnchantedBookRecipeSerializer.java │ │ ├── render/ │ │ │ ├── BakedModelOverrideRegistry.java │ │ │ ├── ConstantsCable.java │ │ │ ├── FluidRenderer.java │ │ │ ├── RenderSettings.java │ │ │ ├── Styles.java │ │ │ ├── blockentity/ │ │ │ │ ├── PatternItemBlockEntityRenderer.java │ │ │ │ └── StorageMonitorBlockEntityRenderer.java │ │ │ ├── collision/ │ │ │ │ └── CollisionGroup.java │ │ │ ├── color/ │ │ │ │ └── PatternItemColor.java │ │ │ ├── model/ │ │ │ │ ├── CubeBuilder.java │ │ │ │ ├── DiskDriveGeometryLoader.java │ │ │ │ ├── DiskDriveUnbakedGeometry.java │ │ │ │ ├── DiskManipulatorGeometryLoader.java │ │ │ │ ├── DiskManipulatorUnbakedGeometry.java │ │ │ │ ├── PortableGridGeometryLoader.java │ │ │ │ ├── PortableGridUnbakedGeometry.java │ │ │ │ └── baked/ │ │ │ │ ├── CableCoverBakedModel.java │ │ │ │ ├── CableCoverItemBakedModel.java │ │ │ │ ├── DiskDriveBakedModel.java │ │ │ │ ├── DiskManipulatorBakedModel.java │ │ │ │ ├── PatternBakedModel.java │ │ │ │ ├── PortableGridBakedModel.java │ │ │ │ └── PortableGridItemBakedModel.java │ │ │ └── resourcepack/ │ │ │ ├── RSResourcePackSection.java │ │ │ ├── RSResourcePackSectionDeserializer.java │ │ │ └── ResourcePackListener.java │ │ ├── screen/ │ │ │ ├── AmountSpecifyingScreen.java │ │ │ ├── BaseScreen.java │ │ │ ├── ConstructorScreen.java │ │ │ ├── ControllerScreen.java │ │ │ ├── CrafterBlockEntitySynchronizationClientListener.java │ │ │ ├── CrafterManagerScreen.java │ │ │ ├── CrafterScreen.java │ │ │ ├── CraftingMonitorScreen.java │ │ │ ├── DestructorScreen.java │ │ │ ├── DetectorScreen.java │ │ │ ├── DiskDriveScreen.java │ │ │ ├── DiskManipulatorScreen.java │ │ │ ├── EmptyScreenInfoProvider.java │ │ │ ├── ExporterScreen.java │ │ │ ├── ExternalStorageScreen.java │ │ │ ├── FilterScreen.java │ │ │ ├── FluidAmountScreen.java │ │ │ ├── FluidInterfaceScreen.java │ │ │ ├── FluidStorageBlockScreen.java │ │ │ ├── IScreenInfoProvider.java │ │ │ ├── ImporterScreen.java │ │ │ ├── InterfaceScreen.java │ │ │ ├── ItemAmountScreen.java │ │ │ ├── KeyInputListener.java │ │ │ ├── NetworkTransmitterScreen.java │ │ │ ├── PriorityScreen.java │ │ │ ├── RelayScreen.java │ │ │ ├── SecurityManagerScreen.java │ │ │ ├── StorageBlockScreen.java │ │ │ ├── StorageMonitorScreen.java │ │ │ ├── StorageScreen.java │ │ │ ├── StorageScreenSynchronizationParameters.java │ │ │ ├── WirelessTransmitterScreen.java │ │ │ ├── factory/ │ │ │ │ ├── CrafterManagerScreenFactory.java │ │ │ │ └── GridScreenFactory.java │ │ │ ├── grid/ │ │ │ │ ├── AlternativesScreen.java │ │ │ │ ├── CraftingPreviewScreen.java │ │ │ │ ├── CraftingSettingsScreen.java │ │ │ │ ├── GridScreen.java │ │ │ │ ├── SmallClientTooltipComponent.java │ │ │ │ ├── filtering/ │ │ │ │ │ ├── AndGridFilter.java │ │ │ │ │ ├── CraftableGridFilter.java │ │ │ │ │ ├── FilterGridFilter.java │ │ │ │ │ ├── GridFilterParser.java │ │ │ │ │ ├── ModGridFilter.java │ │ │ │ │ ├── NameGridFilter.java │ │ │ │ │ ├── OrGridFilter.java │ │ │ │ │ ├── TagGridFilter.java │ │ │ │ │ └── TooltipGridFilter.java │ │ │ │ ├── sorting/ │ │ │ │ │ ├── IGridSorter.java │ │ │ │ │ ├── IdGridSorter.java │ │ │ │ │ ├── LastModifiedGridSorter.java │ │ │ │ │ ├── NameGridSorter.java │ │ │ │ │ ├── QuantityGridSorter.java │ │ │ │ │ └── SortingDirection.java │ │ │ │ ├── stack/ │ │ │ │ │ ├── FluidGridStack.java │ │ │ │ │ ├── IGridStack.java │ │ │ │ │ └── ItemGridStack.java │ │ │ │ └── view/ │ │ │ │ ├── GridViewImpl.java │ │ │ │ └── IGridView.java │ │ │ └── widget/ │ │ │ ├── ScrollbarWidget.java │ │ │ ├── ScrollbarWidgetListener.java │ │ │ ├── SearchWidget.java │ │ │ ├── SmallCheckboxWidget.java │ │ │ ├── TabListWidget.java │ │ │ └── sidebutton/ │ │ │ ├── AccessTypeSideButton.java │ │ │ ├── ConstructorDropSideButton.java │ │ │ ├── CrafterManagerSearchBoxModeSideButton.java │ │ │ ├── CrafterModeSideButton.java │ │ │ ├── DestructorPickupSideButton.java │ │ │ ├── DetectorModeSideButton.java │ │ │ ├── ExactModeSideButton.java │ │ │ ├── FilterTypeSideButton.java │ │ │ ├── GridSearchBoxModeSideButton.java │ │ │ ├── GridSizeSideButton.java │ │ │ ├── GridSortingDirectionSideButton.java │ │ │ ├── GridSortingTypeSideButton.java │ │ │ ├── GridViewTypeSideButton.java │ │ │ ├── IoModeSideButton.java │ │ │ ├── RedstoneModeSideButton.java │ │ │ ├── SearchBoxModeSideButton.java │ │ │ ├── SideButton.java │ │ │ ├── TypeSideButton.java │ │ │ └── WhitelistBlacklistSideButton.java │ │ ├── setup/ │ │ │ ├── ClientSetup.java │ │ │ ├── CommonSetup.java │ │ │ └── ServerSetup.java │ │ └── util/ │ │ ├── AccessTypeUtils.java │ │ ├── BlockColorMap.java │ │ ├── BlockUtils.java │ │ ├── CollisionUtils.java │ │ ├── ColorMap.java │ │ ├── DirectionUtils.java │ │ ├── ItemColorMap.java │ │ ├── ItemStackKey.java │ │ ├── LevelUtils.java │ │ ├── NetworkUtils.java │ │ ├── PacketBufferUtils.java │ │ ├── PlayerUtils.java │ │ ├── RenderUtils.java │ │ ├── StackUtils.java │ │ └── TimeUtils.java │ └── resources/ │ ├── META-INF/ │ │ ├── accesstransformer.cfg │ │ └── mods.toml │ ├── assets/ │ │ └── refinedstorage/ │ │ ├── blockstates/ │ │ │ ├── 1024k_fluid_storage_block.json │ │ │ ├── 16k_storage_block.json │ │ │ ├── 1k_storage_block.json │ │ │ ├── 256k_fluid_storage_block.json │ │ │ ├── 4096k_fluid_storage_block.json │ │ │ ├── 4k_storage_block.json │ │ │ ├── 64k_fluid_storage_block.json │ │ │ ├── 64k_storage_block.json │ │ │ ├── cable.json │ │ │ ├── constructor.json │ │ │ ├── creative_fluid_storage_block.json │ │ │ ├── creative_portable_grid.json │ │ │ ├── creative_storage_block.json │ │ │ ├── destructor.json │ │ │ ├── disk_drive.json │ │ │ ├── exporter.json │ │ │ ├── external_storage.json │ │ │ ├── fluid_interface.json │ │ │ ├── importer.json │ │ │ ├── interface.json │ │ │ ├── machine_casing.json │ │ │ ├── portable_grid.json │ │ │ ├── quartz_enriched_iron_block.json │ │ │ └── storage_monitor.json │ │ ├── lang/ │ │ │ ├── de_de.json │ │ │ ├── en_us.json │ │ │ ├── es_es.json │ │ │ ├── fr_fr.json │ │ │ ├── hu_hu.json │ │ │ ├── it_it.json │ │ │ ├── ja_jp.json │ │ │ ├── ko_kr.json │ │ │ ├── nl_nl.json │ │ │ ├── pl_pl.json │ │ │ ├── pt_br.json │ │ │ ├── ru_ru.json │ │ │ ├── zh_cn.json │ │ │ └── zh_tw.json │ │ ├── models/ │ │ │ ├── block/ │ │ │ │ ├── 1024k_fluid_storage_block.json │ │ │ │ ├── 16k_storage_block.json │ │ │ │ ├── 1k_storage_block.json │ │ │ │ ├── 256k_fluid_storage_block.json │ │ │ │ ├── 4096k_fluid_storage_block.json │ │ │ │ ├── 4k_storage_block.json │ │ │ │ ├── 64k_fluid_storage_block.json │ │ │ │ ├── 64k_storage_block.json │ │ │ │ ├── cable_core.json │ │ │ │ ├── cable_extension.json │ │ │ │ ├── constructor_connected.json │ │ │ │ ├── constructor_destructor.json │ │ │ │ ├── constructor_destructor_nonemissive.json │ │ │ │ ├── constructor_disconnected.json │ │ │ │ ├── controller_nearly.json │ │ │ │ ├── creative_fluid_storage_block.json │ │ │ │ ├── creative_storage_block.json │ │ │ │ ├── cube_all_cutout.json │ │ │ │ ├── cube_all_cutout_nonemissive.json │ │ │ │ ├── cube_cutout.json │ │ │ │ ├── cube_cutout_nonemissive.json │ │ │ │ ├── cube_north_cutout.json │ │ │ │ ├── cube_north_cutout_nonemissive.json │ │ │ │ ├── destructor_connected.json │ │ │ │ ├── destructor_disconnected.json │ │ │ │ ├── detector.json │ │ │ │ ├── detector_nonemissive.json │ │ │ │ ├── disk_drive.json │ │ │ │ ├── disk_drive_base.json │ │ │ │ ├── disks/ │ │ │ │ │ ├── disk.json │ │ │ │ │ ├── disk_disconnected.json │ │ │ │ │ ├── disk_full.json │ │ │ │ │ ├── disk_near_capacity.json │ │ │ │ │ ├── portable_grid_disk.json │ │ │ │ │ ├── portable_grid_disk_disconnected.json │ │ │ │ │ ├── portable_grid_disk_full.json │ │ │ │ │ └── portable_grid_disk_near_capacity.json │ │ │ │ ├── exporter.json │ │ │ │ ├── external_storage.json │ │ │ │ ├── fluid_interface_connected.json │ │ │ │ ├── fluid_interface_disconnected.json │ │ │ │ ├── importer.json │ │ │ │ ├── interface_connected.json │ │ │ │ ├── interface_disconnected.json │ │ │ │ ├── machine_casing.json │ │ │ │ ├── portable_grid.json │ │ │ │ ├── portable_grid_base.json │ │ │ │ ├── portable_grid_connected.json │ │ │ │ ├── portable_grid_disconnected.json │ │ │ │ ├── quartz_enriched_iron_block.json │ │ │ │ ├── storage_monitor.json │ │ │ │ ├── wireless_transmitter.json │ │ │ │ └── wireless_transmitter_nonemissive.json │ │ │ └── item/ │ │ │ ├── 1024k_fluid_storage_block.json │ │ │ ├── 1024k_fluid_storage_disk.json │ │ │ ├── 1024k_fluid_storage_part.json │ │ │ ├── 16k_storage_block.json │ │ │ ├── 16k_storage_disk.json │ │ │ ├── 16k_storage_part.json │ │ │ ├── 1k_storage_block.json │ │ │ ├── 1k_storage_disk.json │ │ │ ├── 1k_storage_part.json │ │ │ ├── 256k_fluid_storage_block.json │ │ │ ├── 256k_fluid_storage_disk.json │ │ │ ├── 256k_fluid_storage_part.json │ │ │ ├── 4096k_fluid_storage_block.json │ │ │ ├── 4096k_fluid_storage_disk.json │ │ │ ├── 4096k_fluid_storage_part.json │ │ │ ├── 4k_storage_block.json │ │ │ ├── 4k_storage_disk.json │ │ │ ├── 4k_storage_part.json │ │ │ ├── 64k_fluid_storage_block.json │ │ │ ├── 64k_fluid_storage_disk.json │ │ │ ├── 64k_fluid_storage_part.json │ │ │ ├── 64k_storage_block.json │ │ │ ├── 64k_storage_disk.json │ │ │ ├── 64k_storage_part.json │ │ │ ├── advanced_processor.json │ │ │ ├── basic_processor.json │ │ │ ├── cable.json │ │ │ ├── construction_core.json │ │ │ ├── constructor.json │ │ │ ├── crafting_upgrade.json │ │ │ ├── creative_fluid_storage_block.json │ │ │ ├── creative_fluid_storage_disk.json │ │ │ ├── creative_portable_grid.json │ │ │ ├── creative_storage_block.json │ │ │ ├── creative_storage_disk.json │ │ │ ├── creative_wireless_crafting_monitor.json │ │ │ ├── creative_wireless_fluid_grid.json │ │ │ ├── creative_wireless_grid.json │ │ │ ├── destruction_core.json │ │ │ ├── destructor.json │ │ │ ├── disk_drive.json │ │ │ ├── exporter.json │ │ │ ├── external_storage.json │ │ │ ├── filter.json │ │ │ ├── fluid_interface.json │ │ │ ├── fortune_1_upgrade.json │ │ │ ├── fortune_2_upgrade.json │ │ │ ├── fortune_3_upgrade.json │ │ │ ├── importer.json │ │ │ ├── improved_processor.json │ │ │ ├── interface.json │ │ │ ├── machine_casing.json │ │ │ ├── network_card.json │ │ │ ├── pattern.json │ │ │ ├── portable_grid.json │ │ │ ├── processor_binding.json │ │ │ ├── quartz_enriched_iron.json │ │ │ ├── quartz_enriched_iron_block.json │ │ │ ├── range_upgrade.json │ │ │ ├── raw_advanced_processor.json │ │ │ ├── raw_basic_processor.json │ │ │ ├── raw_improved_processor.json │ │ │ ├── regulator_upgrade.json │ │ │ ├── security_card.json │ │ │ ├── security_card_active.json │ │ │ ├── security_card_inactive.json │ │ │ ├── silicon.json │ │ │ ├── silk_touch_upgrade.json │ │ │ ├── speed_upgrade.json │ │ │ ├── stack_upgrade.json │ │ │ ├── storage_housing.json │ │ │ ├── storage_monitor.json │ │ │ ├── upgrade.json │ │ │ ├── wireless_crafting_monitor.json │ │ │ ├── wireless_crafting_monitor_connected.json │ │ │ ├── wireless_crafting_monitor_disconnected.json │ │ │ ├── wireless_fluid_grid.json │ │ │ ├── wireless_fluid_grid_connected.json │ │ │ ├── wireless_fluid_grid_disconnected.json │ │ │ ├── wireless_grid.json │ │ │ ├── wireless_grid_connected.json │ │ │ ├── wireless_grid_disconnected.json │ │ │ └── wrench.json │ │ └── textures/ │ │ └── block/ │ │ ├── constructor/ │ │ │ └── cutouts/ │ │ │ └── connected.png.mcmeta │ │ ├── controller/ │ │ │ └── cutouts/ │ │ │ ├── black.png.mcmeta │ │ │ ├── blue.png.mcmeta │ │ │ ├── brown.png.mcmeta │ │ │ ├── cyan.png.mcmeta │ │ │ ├── gray.png.mcmeta │ │ │ ├── green.png.mcmeta │ │ │ ├── light_blue.png.mcmeta │ │ │ ├── light_gray.png.mcmeta │ │ │ ├── lime.png.mcmeta │ │ │ ├── magenta.png.mcmeta │ │ │ ├── nearly_off.png.mcmeta │ │ │ ├── nearly_off_gray.png.mcmeta │ │ │ ├── nearly_on.png.mcmeta │ │ │ ├── nearly_on_gray.png.mcmeta │ │ │ ├── on.png.mcmeta │ │ │ ├── orange.png.mcmeta │ │ │ ├── pink.png.mcmeta │ │ │ ├── purple.png.mcmeta │ │ │ ├── red.png.mcmeta │ │ │ ├── white.png.mcmeta │ │ │ └── yellow.png.mcmeta │ │ └── destructor/ │ │ └── cutouts/ │ │ └── connected.png.mcmeta │ ├── data/ │ │ ├── curios/ │ │ │ └── tags/ │ │ │ └── items/ │ │ │ └── curio.json │ │ ├── forge/ │ │ │ └── tags/ │ │ │ └── items/ │ │ │ └── silicon.json │ │ └── refinedstorage/ │ │ ├── advancements/ │ │ │ ├── autocrafting.json │ │ │ ├── better_than_a_barrel.json │ │ │ ├── conditional_connecting.json │ │ │ ├── connecting.json │ │ │ ├── construction.json │ │ │ ├── crafting_on_demand.json │ │ │ ├── destruction.json │ │ │ ├── detecting.json │ │ │ ├── drives.json │ │ │ ├── exporting.json │ │ │ ├── importing.json │ │ │ ├── interface_to_the_world.json │ │ │ ├── managing_patterns.json │ │ │ ├── manipulating_disks.json │ │ │ ├── monitoring.json │ │ │ ├── no_cables_required.json │ │ │ ├── pattern_creation.json │ │ │ ├── portable_storage.json │ │ │ ├── root.json │ │ │ ├── security.json │ │ │ ├── storing_externally.json │ │ │ ├── storing_fluids.json │ │ │ ├── storing_items.json │ │ │ ├── upgrading.json │ │ │ ├── upgrading_your_grid.json │ │ │ ├── viewing_fluids.json │ │ │ ├── viewing_items.json │ │ │ ├── wireless.json │ │ │ ├── wireless_fluids.json │ │ │ ├── wireless_items.json │ │ │ └── wireless_monitoring.json │ │ ├── loot_tables/ │ │ │ └── blocks/ │ │ │ ├── 1024k_fluid_storage_block.json │ │ │ ├── 16k_storage_block.json │ │ │ ├── 1k_storage_block.json │ │ │ ├── 256k_fluid_storage_block.json │ │ │ ├── 4096k_fluid_storage_block.json │ │ │ ├── 4k_storage_block.json │ │ │ ├── 64k_fluid_storage_block.json │ │ │ ├── 64k_storage_block.json │ │ │ ├── cable.json │ │ │ ├── constructor.json │ │ │ ├── creative_fluid_storage_block.json │ │ │ ├── creative_portable_grid.json │ │ │ ├── creative_storage_block.json │ │ │ ├── destructor.json │ │ │ ├── disk_drive.json │ │ │ ├── exporter.json │ │ │ ├── external_storage.json │ │ │ ├── fluid_interface.json │ │ │ ├── importer.json │ │ │ ├── interface.json │ │ │ ├── machine_casing.json │ │ │ ├── portable_grid.json │ │ │ ├── quartz_enriched_iron_block.json │ │ │ └── storage_monitor.json │ │ ├── recipes/ │ │ │ ├── 1024k_fluid_storage_block.json │ │ │ ├── 1024k_fluid_storage_disk.json │ │ │ ├── 1024k_fluid_storage_disk_from_storage_housing.json │ │ │ ├── 1024k_fluid_storage_part.json │ │ │ ├── 16k_storage_block.json │ │ │ ├── 16k_storage_disk.json │ │ │ ├── 16k_storage_disk_from_storage_housing.json │ │ │ ├── 16k_storage_part.json │ │ │ ├── 1k_storage_block.json │ │ │ ├── 1k_storage_disk.json │ │ │ ├── 1k_storage_disk_from_storage_housing.json │ │ │ ├── 1k_storage_part.json │ │ │ ├── 256k_fluid_storage_block.json │ │ │ ├── 256k_fluid_storage_disk.json │ │ │ ├── 256k_fluid_storage_disk_from_storage_housing.json │ │ │ ├── 256k_fluid_storage_part.json │ │ │ ├── 4096k_fluid_storage_block.json │ │ │ ├── 4096k_fluid_storage_disk.json │ │ │ ├── 4096k_fluid_storage_disk_from_storage_housing.json │ │ │ ├── 4096k_fluid_storage_part.json │ │ │ ├── 4k_storage_block.json │ │ │ ├── 4k_storage_disk.json │ │ │ ├── 4k_storage_disk_from_storage_housing.json │ │ │ ├── 4k_storage_part.json │ │ │ ├── 64k_fluid_storage_block.json │ │ │ ├── 64k_fluid_storage_disk.json │ │ │ ├── 64k_fluid_storage_disk_from_storage_housing.json │ │ │ ├── 64k_fluid_storage_part.json │ │ │ ├── 64k_storage_block.json │ │ │ ├── 64k_storage_disk.json │ │ │ ├── 64k_storage_disk_from_storage_housing.json │ │ │ ├── 64k_storage_part.json │ │ │ ├── advanced_processor.json │ │ │ ├── basic_processor.json │ │ │ ├── block_of_quartz_enriched_iron.json │ │ │ ├── cable.json │ │ │ ├── construction_core.json │ │ │ ├── constructor.json │ │ │ ├── controller.json │ │ │ ├── cover.json │ │ │ ├── crafter.json │ │ │ ├── crafter_manager.json │ │ │ ├── crafting_monitor.json │ │ │ ├── crafting_upgrade.json │ │ │ ├── destruction_core.json │ │ │ ├── destructor.json │ │ │ ├── detector.json │ │ │ ├── disk_drive.json │ │ │ ├── disk_manipulator.json │ │ │ ├── exporter.json │ │ │ ├── external_storage.json │ │ │ ├── filter.json │ │ │ ├── fluid_interface.json │ │ │ ├── fortune_1_upgrade.json │ │ │ ├── fortune_2_upgrade.json │ │ │ ├── fortune_3_upgrade.json │ │ │ ├── grid.json │ │ │ ├── hollow_cover.json │ │ │ ├── importer.json │ │ │ ├── improved_processor.json │ │ │ ├── interface.json │ │ │ ├── machine_casing.json │ │ │ ├── network_card.json │ │ │ ├── network_receiver.json │ │ │ ├── network_transmitter.json │ │ │ ├── pattern.json │ │ │ ├── portable_grid.json │ │ │ ├── processor_binding.json │ │ │ ├── quartz_enriched_iron.json │ │ │ ├── quartz_enriched_iron_from_block.json │ │ │ ├── range_upgrade.json │ │ │ ├── raw_advanced_processor.json │ │ │ ├── raw_basic_processor.json │ │ │ ├── raw_improved_processor.json │ │ │ ├── regulator_upgrade.json │ │ │ ├── relay.json │ │ │ ├── security_card.json │ │ │ ├── security_manager.json │ │ │ ├── silicon.json │ │ │ ├── silk_touch_upgrade.json │ │ │ ├── speed_upgrade.json │ │ │ ├── stack_upgrade.json │ │ │ ├── storage_housing.json │ │ │ ├── storage_monitor.json │ │ │ ├── upgrade.json │ │ │ ├── wireless_crafting_monitor.json │ │ │ ├── wireless_fluid_grid.json │ │ │ ├── wireless_grid.json │ │ │ ├── wireless_transmitter.json │ │ │ └── wrench.json │ │ └── tags/ │ │ └── items/ │ │ └── crafting_tables.json │ └── pack.mcmeta └── tools/ └── missing-translation-keys.sh ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/CONTRIBUTING.md ================================================ # Contributing When contributing to this repository, please first discuss the change you wish to make via [GitHub issues](https://github.com/refinedmods/refinedstorage/issues), [Discord](https://discordapp.com/invite/VYzsydb), or any other method with the owners of this repository before making a change. ## Pull requests - Keep your pull request (PR) as small as possible, this makes reviewing easier. - Commits serve a clear purpose and have a fitting commit message. - Branches are kept up to date by rebasing (updating a branch by merging makes for a confusing Git history). - PRs are merged by merging the commits on top of the target branch (which is `develop`). - Remember to add your changes in `CHANGELOG.md`. If your changes are merely technical, it's not necessary to update the changelog as it's not relevant for users. ### Commit messages Commit messages must adhere to [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). We use [Commitlint](https://commitlint.js.org/) to validate commit messages. We use the [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional) for Commitlint. It is recommended to install the [Conventional Commit plugin](https://plugins.jetbrains.com/plugin/13389-conventional-commit) to make it easier to write commit messages. ### Branch names Because we use merge commits when merging a PR, branch names will be part of the history of the repository. That is why branch names must follow a certain standard. The format is `{category}/GH-{issue number}/{lowercase-description}` and a branch name can be maximum 50 characters of length. Category must match a category [used in our Commitlint config](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum). Valid examples are: - `fix/GH-123/add-branch-linting` - `docs/GH-123/cleanup` ## Versioning This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Version metadata The code doesn't contain version metadata: `build.gradle` specifies a version of `0.0.0` (via Refined Architect). The versioning information is entirely contained in Git by using tags. Per [Semantic Versioning](https://semver.org/spec/v2.0.0.html), the version number being released depends on the changes in that release. We usually can't predict those changes at the start of a release cycle, so we can't bump the version at the start of a release cycle. That means that the version number being released is determined at release time. Because the version number is determined at release time, we can't store any versioning metadata in the code (`build.gradle`). If we did, `build.gradle` would have the version number of the latest released version during the release cycle of the new version, which isn't correct. ### Dealing with Minecraft Whenever we port to a new Minecraft version, at least the minor version should be incremented. This is needed so that we can still support older Minecraft versions without the version numbers conflicting. ## Changelog The changelog is kept in `CHANGELOG.md`. Keeping a readable, relevant and user-friendly changelog is essential for our end users to stay up to date with the project. Please refrain from using technical terminology or adding entries for technical changes that are (generally) not relevant to the end-user. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Gitflow This project uses [Gitflow](https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow). ## Documentation Documentation must be kept up to date when adding or changing functionality. ### Javadoc Javadoc is available after every release on https://refinedmods.com/javadoc/refinedstorage. ### API annotations Public APIs must be annotated with an `@API` annotation from [API Guardian](https://github.com/apiguardian-team/apiguardian). ## Code style We use [Checkstyle](https://checkstyle.sourceforge.io/) in our build workflow to validate coding style. It is recommended to import the [config/checkstyle/checkstyle.xml](../config/checkstyle/checkstyle.xml) file into your IDE, so that formatting rules are respected. Moreover, the [CheckStyle-IDEA plugin](https://plugins.jetbrains.com/plugin/1065-checkstyle-idea) can be used to check if there are no style violations. ## Release process The release process is automated and follows Gitflow. Before running the "Draft release" workflow to start the release process make sure `CHANGELOG.md` contains all the unreleased changes. To determine the version number to be released, the workflow will ask you which release type this is (major, minor, patch). The latest version from `CHANGELOG.md` will be used as a base, and that will be incremented depending on the release type. `CHANGELOG.md` will be updated by this workflow, you can review this in the resulting release PR. If you merge the release PR, the "Publish release" workflow will automatically publish the release. An additional PR will be created to merge the changes in `CHANGELOG.md` back into `develop`. ## Hotfix process The hotfix process is semi-automated and follows Gitflow: - Create a hotfix branch off `main`. - Commit your changes on this branch. - Update `CHANGELOG.md` (with version number and release date) manually on this branch. - Push the branch and create a PR for it, merging into `main`. The "Publish release" workflow will take care of the rest. ## Workflows We have a few GitHub workflows: - Build (PRs, pushes to `develop` and `main`) - Draft release (manual trigger) - Publish release (merging a PR to `main`) - Validate changelog (PRs) - To validate if `CHANGELOG.md` is valid and updated. - Not every pull request needs a changelog change, so the `skip-changelog` label can be added to the pull request to ignore this. - Validate commit messages (PRs) - Validates whether the commits on a pull request respect [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/). - We use the [conventional configuration](https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional). - Validate branch names (PRs) - Issue for unsupported version (issues) - Posts a message on a GitHub issue if the issue is about an unsupported version. - Lock resolved issues and PRs (every night) ### Build The build workflow triggers when a pull request is updated or when a commit is pushed to `develop` or `main`. The build workflow takes care of the following: - Running a Gradle build, running our tests in the process and generating an aggregated code coverage report for the API modules. - Code style validation with Checkstyle. - Mutation and line coverage test with Pitest. - Uploading the artifacts on the action. ### Draft release The draft release workflow is a manual workflow which will create a release branch from `develop`. To determine the version number to be released, it will extract the latest version number from `CHANGELOG.md` and increment it depending on the release type selected. This workflow takes care of the following: - Creating the release branch. - Updating the changelog on this release branch. - Creating a pull request merging the release branch into `main`. ### Publish release The "publish release" workflow is triggered when a release or hotfix PR is merged to `main`. Usually, this will be the PR created earlier in the "Draft release" workflow. The workflow takes care of the following: - Extracting the version number from the release or hotfix branch name that is merged in the PR. - Extracting the changelog entry for this version number. - Running a build. - Publishing on [GitHub packages](https://github.com/refinedmods/refinedstorage/packages) and CreeperHost Maven. - Publishing Javadoc on [GitHub pages](https://github.com/refinedmods/javadoc). - Deploying on [GitHub releases](https://github.com/refinedmods/refinedstorage/releases). - Announcing the release on Discord and Twitter. - Creating a PR that merges `main` back into `develop` to get the changes to `CHANGELOG.md` and `build.gradle` into `develop` from the draft release workflow. ================================================ FILE: .github/FUNDING.yml ================================================ patreon: raoulvdberge ko_fi: raoulvdberge ================================================ FILE: .github/ISSUE_TEMPLATE/config.yml ================================================ blank_issues_enabled: false contact_links: - name: 🚫 No support for v1.x url: https://refinedmods.com/refined-storage/need-help.html#_supported_versions about: Refined Storage v1.x is no longer maintained. We do not accept issues or provide support for it. - name: 🛠 Refined Storage v2.x Issue Tracker url: https://github.com/refinedmods/refinedstorage2/issues about: Report all bugs, suggestions, and support requests for Refined Storage v2.x here. - name: Discord Community Support url: https://discordapp.com/invite/VYzsydb about: Please ask and answer questions here. Issues should be used for bugs and feature requests. ================================================ FILE: .github/SUPPORT.md ================================================ # Support If you have a problem and need help, we offer various channels where you can ask for help. ## I have a question Questions can be asked on [Discord](https://discordapp.com/invite/VYzsydb). ## I have found a bug If you have found a bug, please report it on [GitHub issues](https://github.com/refinedmods/refinedstorage/issues). ================================================ FILE: .github/workflows/build.yml ================================================ name: Build on: push: branches: - develop - main pull_request: types: [ opened, synchronize, reopened ] jobs: build: uses: refinedmods/refinedarchitect/.github/workflows/build.yml@v0.11.4 with: mutation-testing: false sonarqube: false secrets: inherit ================================================ FILE: .github/workflows/draft-release.yml ================================================ name: Draft release on: workflow_dispatch: inputs: release-type: description: 'Release type' required: true default: 'minor' type: choice options: - major - minor - patch version-number-override: description: 'Version number override' required: false type: string jobs: draft: uses: refinedmods/refinedarchitect/.github/workflows/draft-release.yml@v0.11.4 with: release-type: ${{ inputs.release-type }} version-number-override: ${{ inputs.version-number-override }} secrets: inherit ================================================ FILE: .github/workflows/issue-for-unsupported-version.yml ================================================ name: Issue for unsupported version on: issues: types: [ labeled, unlabeled, reopened ] jobs: unsupported-labeler: uses: refinedmods/refinedarchitect/.github/workflows/issue-for-unsupported-version.yml@v0.11.4 ================================================ FILE: .github/workflows/publish-release.yml ================================================ name: Publish release on: pull_request: branches: - main types: - closed jobs: publish-release: uses: refinedmods/refinedarchitect/.github/workflows/publish-release.yml@v0.11.4 secrets: inherit with: project-name: 'Refined Storage' announce: true mutation-testing: false curseforge: true modrinth: true sonarqube: false ================================================ FILE: .github/workflows/resolved-issue-locking.yml ================================================ name: Lock resolved issues and PRs on: schedule: - cron: '0 0 * * *' jobs: lock: uses: refinedmods/refinedarchitect/.github/workflows/resolved-issue-locking.yml@v0.11.4 ================================================ FILE: .github/workflows/validate-branch-name.yml ================================================ name: Validate branch name on: [ pull_request ] jobs: validate-branch-name: uses: refinedmods/refinedarchitect/.github/workflows/validate-branch-name.yml@v0.11.4 ================================================ FILE: .github/workflows/validate-changelog.yml ================================================ name: Validate changelog on: pull_request: types: [ opened, synchronize, reopened, ready_for_review, labeled, unlabeled ] jobs: validate-changelog: uses: refinedmods/refinedarchitect/.github/workflows/validate-changelog.yml@v0.11.4 with: validation-level: 'warn' ================================================ FILE: .github/workflows/validate-commit-messages.yml ================================================ name: Validate commit messages on: [ pull_request ] jobs: validate-commit-messages: uses: refinedmods/refinedarchitect/.github/workflows/validate-commit-messages.yml@v0.11.4 ================================================ FILE: .gitignore ================================================ .gradle/ .nb-gradle/ .settings/ build/ eclipse/ .classpath .nb-gradle-properties .project *.launch runs/ *.iml *.ipr *.iws .idea/ out/ /bin/ logs/ **/.DS_Store ================================================ FILE: CHANGELOG.md ================================================ # Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] ## [1.13.0-beta.4] - 2024-03-07 ### Added - Added Hungarian translation. ### Fixed - Fixed an error that occurred when targeting the crafter with Jade installed ## [1.13.0-beta.3] - 2024-03-05 ### Fixed - Fixed items in disks deserializing with an empty NBT tag. - Fixed placing fluids in the pattern grid disconnecting the client. ## [1.13.0-beta.2] - 2024-02-16 ### Fixed - Fixed JEI transfer in the Pattern Grid wrongly choosing "Processing" mode. - Fixed JEI transfer not working in single player. ## [1.13.0-beta.1] - 2024-02-12 ### Added - Ported to Minecraft 1.20.4. ## [1.12.4] - 2023-11-05 ### Added - Re-added compatibility with Inventory Sorter. ### Fixed - Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod. - Fixed Grid search bar not being able to lose focus. - Fixed JEI transfer crash for larger processing recipes. - Fixed rare autocrafting crash. - Fixed some models in inactive state being emissive. - Fixed Controller item not rendering energy state correctly. - Fixed duplication bug with the Crafting Grid. - Fixed fluid duplication bug with the Importer and GregTechCEu machines. - Attempted to fix issue where Grid doesn't load items and requires a client restart. - Fixed Crafter Manager slots being able to sort with Inventory Sorter. - Fixed duplication bug in the Crafter with Inventory Sorter. ## [1.12.3] - 2023-07-07 ### Fixed - Fixed not being able to type "e" in Grid search box. ## [1.12.2] - 2023-07-05 ### Fixed - The Grid detailed tooltip now has a small font size again. - Fixed not being able to close GUIs anymore with autoselected search box mode. - Fixed lingering tooltips of side buttons. ## [1.12.1] - 2023-07-03 ### Fixed - Fixed packages not being published to Maven. ## [1.12.0] - 2023-07-03 ### Changed - Ported to Minecraft 1.20.1. ### Fixed - Fixed GUI side buttons not working sometimes when using Refined Storage with addons. ## [1.11.7] - 2023-11-12 ### Fixed - Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod. - Fixed JEI transfer crash for larger processing recipes. - Fixed rare autocrafting crash. - Fixed duplication bug with the Crafting Grid. - Fixed fluid duplication bug with the Importer and GregTechCEu machines. - Attempted to fix issue where Grid doesn't load items and requires a client restart. ## [1.11.6] - 2023-03-30 ### Fixed - Fixed not being able to search with JEI when the Grid is open. - Fixed a bunch of issues where chunks would unintentionally be loaded by RS. - Reduced block updates when a controller is turning on and off constantly. ## [1.11.5] - 2023-02-12 ### Fixed - Fixed some craftable items not showing as craftable in JEI - Fixed Grid crashing on exit if JEI mod is not used - Fixed rare multithreading crash - Fixed Constructor being able to drop more than the maximum stack size for an item ## [1.11.4] - 2022-12-20 ### Fixed - Fixed duplication bug in the Interface. ## [1.11.3] - 2022-12-20 ### Fixed - Fixed external storage cache being de-synced from the network cache. - Fixed external storage using an out of date block entity for getting handler. - Fixed inventory slots being reused incorrectly in rare cases in the JEI transfer handler. ### Changed - Increased packet size limit. ## [1.11.2] - 2022-12-17 ### Added - Available items indicator in JEI now updates while JEI is open. ### Fixed - Fixed chained crafters not taking over the name of the root crafter. - Fixed lag when opening JEI in large systems. - Made Refined Storage more robust against crashes when moving network blocks by unconventional means. ## [1.11.1] - 2022-10-30 ### Fixed - Fixed not using Forge silicon tag for recipes. - Small corrections to the Korean translation. ## [1.11.0] - 2022-09-30 ### Changed - Ported to Minecraft 1.19.2. ## [1.10.6] - 2023-11-26 ### Fixed - Fixed a bunch of issues where chunks would unintentionally be loaded by RS. - Reduced block updates when a controller is turning on and off constantly. - Various world corruption issues if Refined Storage blocks were removed unexpectedly or with another mod. - Fixed JEI transfer crash for larger processing recipes. - Fixed rare autocrafting crash. - Fixed duplication bug with the Crafting Grid. - Fixed fluid duplication bug with the Importer in certain situations. - Attempted to fix issue where Grid doesn't load items and requires a client restart. ## [1.10.5] - 2023-02-12 ### Fixed - Fixed rare multithreading crash - Fixed Constructor being able to drop more than the maximum stack size for an item ## [1.10.4] - 2022-12-20 ### Fixed - Fixed external storage cache being de-synced from the network cache. - Fixed external storage using an out of date block entity for getting handler. - Fixed chained crafters not taking over the name of the root crafter. - Made Refined Storage more robust against crashes when moving network blocks by unconventional means. - Fixed duplication bug in the Interface. ### Changed - Increased packet size limit. ## [1.10.3] - 2022-08-06 ### Fixed - Fixed Destructor dupe bug - Fixed being unable to insert items into the Storage Monitor - Fixed Storage Monitor not showing all matching items in non-exact mode - Fixed items getting lost on Creative Disk when more than 2,147,483,647 of one type is stored - Fixed incorrect autocrafting keybind prompt on macOS - Fixed crashing the game when a network block was removed in a bad way - Fixed duplication bug with Constructors and Shulker Boxes - Fixed breaking blocks with pickaxe taking too much time ### Changed - Improved performance for grid updates - Improved waterlogging to behave more like vanilla - JEI version 9.7.1 or higher is now required ### Added - Forge relocation and Packing Tape blacklist tag entries to prevent block movement - Japanese translations for certain autocrafting actions ## [1.10.2] - 2022-03-26 ### Changed - Ported to Minecraft 1.18.2. ## [1.10.1] - 2022-03-26 ### Fixed - Fixed crash when opening alternatives screen. ## [1.10.0] - 2022-01-25 ### Fixed - Fixed multiple bugs related to transferring recipes into the Crafting Grid. - Processing patterns now use the order of items/fluids specified in the pattern by [@necauqua](https://github.com/necauqua) and [@Darkere](https://github.com/Darkere). - Fixed autocrafting task getting stuck if two tasks fulfilled each others requirements. - Fixed fluid autocrafting breaking when using 2 stacks of the same fluid in a pattern. - Amount specifying screen is now limited to valid values. - Fixed crash on servers when starting with latest Forge. ## [1.10.0-beta.4] - 2021-12-28 ### Fixed - Fixed client crash when hovering over a fluid in the Fluid Grid by [@jackodsteel](https://github.com/jackodsteel). - Fixed random client crashes when starting the game. ### Changed - Update Korean translation by [@mindy15963](https://github.com/mindy15963). ## [1.10.0-beta.3] - 2021-12-17 ### Fixed - Fixed networks and network devices being removed when a chunk unloads. ## [1.10.0-beta.2] - 2021-12-16 ### Fixed - Fixed all Refined Storage advancements being granted when joining a world. - Fixed potential Pattern crash when loading Minecraft. ## [1.10.0-beta.1] - 2021-12-15 ### Fixed - Fixed Relay not working. - Fixed Wireless Transmitter only working upright. - Fixed Portable Grid not opening when pointing at a block. - Fixed being able to circumvent locked slots by scrolling. ### Changed - Added more slots to the Pattern Grid. - Combined fluid and item view in the Pattern Grid. - Ported to Minecraft 1.18.1. - Focused side buttons now display their tooltip properly. - Improved performance of retrieving patterns by [@metalshark](https://github.com/metalshark). ## [1.9.18] - 2022-05-18 ### Fixed - Fixed potential Pattern crash when loading Minecraft. ## [1.9.17] - 2022-01-30 ### Added - More slots for the Pattern Grid. ### Changed - Combined fluid and item view in the Pattern Grid. - Processing patterns now use the order of items/fluids specified in the pattern. - Amount specifying screen is now limited to valid values. ### Fixed - Fixed Relay not working. - Fixed Wireless Transmitter only working upright. - Fixed Portable Grid not opening when pointing at a block. - Fixed being able to circumvent locked slots by scrolling. - Fixed multiple bugs related to transferring recipes into the crafting grid. - Fixed autocrafting task getting stuck if two tasks fulfilled each others requirements. - Fixed fluid autocrafting breaking when using 2 stacks of the same fluid in a pattern. ## [1.9.16] - 2021-11-16 ### Added - Added Covers for all cable types. - Added Polish translation. - Added Italian translation. - Addons can now override how crafters insert items. ### Changed - Improved JEI integration to pick the best option when transferring items. ### Fixed - Fixed an issue where too many items in a grid would kick the player. - Fixed an issue where the portable grid does not open from Inventory anymore after some use. - Fixed craftable view in grids not showing items that were already in storage. - Fixed Wireless Crafting Monitor not working as Curio. - Fixed wrong slot being locked in some cases when opening a wireless item. - Slightly sped up External Storage item look up. - Fixed extraction from Storage Monitor not respecting maximum stack size. ## [1.9.15] - 2021-07-25 ### Fixed - Fixed Refined Storage Addons compatibility. ## [1.9.14] - 2021-07-25 ### Added - Implemented Curios support. ## [1.9.13] - 2021-06-14 ### Added - Added some performance improvements for autocrafting. ### Fixed - Fixed count on Storage Monitor having Z fighting. - Fixed items on Storage Monitor not being flat. - Fixed crash when using an External Storage on a fluid inventory. - Fixed a memory leak in the pattern cache. - Fixed Detector crashing when dyed. - Fixed autocrafting being stuck after clicking "Start". - Fixed Crafting Monitor not being able to show hours. - Fixed capacity rendering of infinite storages. - Fixed wrong alignment for the JEI request autocrafting tooltip. - Fixed mobs getting stuck in Refined Storage cables. - Fixed dismantling storage blocks ignoring stack size. - Fixed Ice and Fire banners breaking with Refined Storage. - Fixed empty keybinding causing GL errors. - Fixed some parts of the Japanese translation. - Fixed rendering issue on blocks when using OptiFine. ### Removed - Removed experimental pipeline nagging message. ## [1.9.12] - 2021-02-07 ### Fixed - Fixed some issues when using the Grid when it's offline. - Fixed crafting events not being fired in some cases in the Grid. - Fixed not being able to set fluid filter slot output quantity. - Fixed mod id search not working for Industrial Foregoing. - Fixed fluid autocrafting duplicating fluids. - Fixed some Grid crashes. - Fixed constructor not using compare mode correctly in some cases. - Fixed duplication bug in the Interface. ## [1.9.11] - 2021-01-03 ### Fixed - Fixed disks and network devices not loading when they did not previously exist - If you are affected by this please go to the world/data/ folder and remove the ".temp" ending from the files before launching. ## [1.9.10] - 2021-01-02 ### Changed - Update Japanese translation. ### Fixed - Improve performance of the Grid view. - Fixed Disk Manipulator model glitches. - Improve performance of the Disk Manipulator. - Fixed being unable to set quantity in output slots of the Pattern Grid. - Fixed External Storage in fluid mode losing track of fluids sometimes. - Added code to avoid / minimize data corruption issues caused by Minecraft. - Fixed processing autocrafting orders stealing items from each other. - Fixed Constructor in fluid mode voiding fluid source blocks in front of it. - Fixed crash when recoloring blocks that have no rotation component. - Fixed reloading resource packs breaking Refined Storage textures. ## [1.9.9] - 2020-11-14 ### Fixed - Fixed Refined Storage sidebuttons displaying over the JEI bookmark pagination buttons. - Fixed issue where Crafters may fail to recognize an inventory/tank for some patterns. - Fixed issue where the Crafter Manager can crash on invalid patterns. - Fixed issue where alternatives in the Pattern Grid weren't being saved properly. - Fixed not being able to change the Exporter filter slot count with regulator mode without closing and re-opening the container. ## [1.9.8] - 2020-10-24 ### Added - Added a JEI synchronized (two-way) search box mode to the Grid. - Added a nag message when a player joins the world that asks the player to enable the experimental Forge lighting pipeline to ensure correct rendering. ### Fixed - Fixed server crash when scrolling in Grid. - Fixed various issues with Grid interactions working without power. - Fixed changing rotation not updating blocks. ## [1.9.7] - 2020-10-04 ### Added - Added functionality to move items in the Grid with shift/ctrl + scrolling. ### Changed - Changed JEI transfer error mechanics. ### Fixed - Fixed crash when opening Controller GUI. - Fixed dye being consumed without effect in some cases. - Fixed deadlock caused by Portable Grid. - Fixed custom tooltips not working in the Grid. ## [1.9.6] - 2020-09-25 ### Added - Port to Minecraft 1.16.3. - Added colored block variants. - Added functionality to show missing items in the JEI transfer screen. - Added functionality to request missing items from autocrafting in the JEI transfer screen. - Added client config option to remember the Grid search query. ### Fixed - Fixed Portable Grid losing enchantments when placing and breaking. ## [1.9.5] - 2020-09-06 ### Added - Re-added the `/refinedstorage disk create ` command. - Added the `/refinedstorage disk list` command. - Added the `/refinedstorage disk list ` command. - Added the `/refinedstorage network list ` command. - Added the `/refinedstorage network get ` command. - Added the `/refinedstorage network get autocrafting list` command. - Added the `/refinedstorage network get autocrafting get ` command. - Added the `/refinedstorage network get autocrafting cancel` command. - Added the `/refinedstorage network get autocrafting cancel ` command. - Added JEI ghost ingredient dragging support. ### Fixed - Fixed text field not being focused in amount specifying screens. ## [1.9.4] - 2020-08-30 ### Fixed - Fixed JEI recipes/usages keys not working in Grids. ## [1.9.3-beta] - 2020-08-24 ### Added - Port to Minecraft 1.16.2. ### Changed - Updated Japanese translation. - Updated Taiwanese translation. - Refactored autocrafting code. ### Fixed - Fixed duplication bug with the Constructor. ## [1.9.2-beta.2] - 2020-09-11 ### Fixed - Fixed duplication bug with the Constructor. ## [1.9.2-beta.1] - 2020-07-17 ### Added - Re-added interdimensional networks with the Network Transmitter and Network Receiver. - Re-added MouseTweaks integration. ### Changed - Networks that are in a chunk that isn't loaded will no longer work, they will turn off. Chunkload the Controller to maintain a functioning network over long distances. ### Fixed - Fixed crash with Forge version 67. - Fixed cases where Refined Storage unwillingly acts like a chunkloader. - Fixed Network Transmitters being able to connect to any network device. - Fixed Crafting Tweaks buttons being in the wrong position after changing the size configuration of the Grid. ## [1.9.1-beta] - 2020-07-14 ### Fixed - Fixed server crash. ## [1.9.0-beta] - 2020-07-14 ### Added - Port to Minecraft 1.16. ### Fixed - Fixed wrench requiring shift click to rotate blocks. ## [1.8.8] - 2020-07-13 ### Fixed - Fixed duplication bug and weird behavior in the Crafting Grid matrix. ## [1.8.7] - 2020-07-11 ### Fixed - Fixed Regulator mode item and fluid counts not saving properly. - Fixed Wireless Crafting Monitor not closing properly. - Fixed Controller always using energy, even when disabled with redstone. - Fixed internal crafting inventory not being returned when Controller is broken. - Fixed bug where autocrafting tasks started on the same tick make the wrong assumption about available items and fluids. - Fixed bug where the "To craft" amount in the Crafting Preview window is wrong. - Fixed bug where non-pattern items are able to be inserted into the Crafter Manager (Darkere) - Fixed performance issue where shapes of cable blocks were constantly being recalculated. ### Changed - Drastically improved shift clicking performance in Crafting Grid. ### Removed - Removed autocrafting engine version from crafting preview screen. ## [1.8.6-beta] - 2020-06-26 ### Fixed - Fixed Constructor duplication bug. ## [1.8.5-beta] - 2020-06-18 ### Added - Re-added all the language files. - Japanese translations. ### Fixed - Fixed Portable Grid voiding the disk when extracting with full inventory. - Fixed Constructor extracting 2 buckets when placing fluid. - Fixed Stack Overflow error with regulator upgrades. - Fixed visual bug with the Detector not updating its values. - Fixed Constructor placing the filtered item instead of the extracted. - Fixed duplication bug with filter slots. - Fixed shift crafting in a Grid not using the player. - Fixed bug where shift clicking gives too many items. ### Changed - Cancelling a crafting task now also unlocks all Crafters related to that task. - External Storage will now always show the exact maximum capacity as reported by the attached inventory. - Crafters no longer expose their inventory to the side they are facing. - Changed package name to `com.refinedmods.refinedstorage`, this is a breaking change for addons. ## [1.8.4-beta] - 2020-05-26 ### Fixed - Fixed autocrafting Crafting Monitor crash. ## [1.8.3-beta] - 2020-04-29 ### Added - A new experimental autocrafting engine that's enabled by default. This should improve autocrafting performance. - The Regulator Upgrade that can be inserted into a Exporter. This ensures a certain amount of items and fluids is kept in stock in a connected inventory. - Debug logging on the server when an expensive operation occurs. ### Fixed - Fixed Exporter not exporting anything when using a Stack Upgrade and there isn't space for 64 items in the inventory. - Fixed Controller always using the base usage even when turned off. - Fixed severe memory leak in the storage cache. ### Changed - Wireless Transmitters can now be placed on any block and in any direction. ## [1.8.2-beta] - 2020-04-25 ### Added - Refined Storage silicon is now present in `forge:silicon` tag for mod compatibility. - Waterlogging to all cable blocks. - Create zh_tw translation. - Re-added zh_cn translation. ### Fixed - Fixed storage block dropping extra processor. ### Changed - Updated pt_br translation. ## [1.8.1-beta] - 2020-01-30 ### Added - Port to Minecraft 1.15.2. - Fluid support for the Storage Monitor. ## [1.8.0-beta] - 2020-01-21 ### Added - Port to Minecraft 1.15. ## [1.7.3-beta] - 2019-12-30 ### Fixed - Fixed severe energy update lag introduced by version 1.7.2. ## [1.7.2-beta] - 2019-12-29 ### Added - Resource packs can now define the font colors that Refined Storage GUIs need to use. ### Fixed - Fixed crash when loading a network. - Fixed being able to drain energy from the Refined Storage Controller. - Fixed the Grid crashing on a item/fluid update-heavy storage system. - Fixed the Grid displaying the old quantity when shift clicking an entire stack out. - Fixed crash with the Disk Manipulator and using item/fluid filters when inserting into the network. - Fixed the network being able to run off 1 FE/t. ### Changed - Patterns being added or removed from the network are now propagated as well to clients that are watching a Grid. - When pressing ESCAPE in the search box on the Grid or Crafter Manager, focus on the search bar will be lost first before closing the GUI immediately. Then on the next ESCAPE press, the GUI will be closed. ## [1.7.1-alpha] - 2019-11-19 ### Fixed - Fixed Pattern Grid causing world hanging on load. - Fixed External Storage not refreshing when the storage is broken or replaced. - Fixed delay in block update when placing a cable block. - Fixed holder of cable blocks sometimes conflicting with a cable connection while rendering. - Fixed being able to move wireless items in inventory when using a keybinding to open. - Fixed crash when breaking a Grid, Crafting Monitor, Crafter Manager or Portable Grid when another player is still using it. ### Changed - The Pattern Grid now switches automatically between crafting pattern and processing pattern mode when using JEI transfer. - The Pattern Grid now switches automatically between crafting pattern and processing pattern mode when re-inserting an existing Pattern. - Grids now do not sort if you interact with it while holding shift. ### Removed - Exact mode for processing patterns no longer exist, you can now define per-slot which item/fluid tags are allowed to be used by autocrafting, by using CTRL + click on the filter slot in the Pattern Grid. - Removed migration code for the development builds that were released on Discord (not on CurseForge). If you used the development builds and never used version 1.7.0 before, first switch to 1.7.0, open your world, modify a storage disk, and then upgrade to 1.7.1. ## [1.7.0-alpha] - 2019-11-02 ### Added - Port to Minecraft 1.14. ### Fixed - Fixed the Fluid Grid not having a View type setting. ### Changed - Oredict mode for Patterns has been replaced with "Exact mode" (by default on). When exact mode is off, Refined Storage will use equivalent items or fluids from the Minecraft item/fluid tag system. - Grid filtering with "$" now does filtering based on item/fluid tag name instead of oredict name. - When binding a network item to a network you can now bind to any network block, not only the Controller. ### Removed - The Reader and Writer, this will return later in an addon mod. - Cross dimensional functionality on the Network Transmitter for the moment, this will return later. - Covers. ## [1.7.0+10] - 2019-10-29 ### Added - Re-added oredict mode as "exact mode" (for fluids too!). - Re-added the Crafter Manager. - Re-added the Crafting Monitor. - Re-added the Wireless Crafting Monitor. ### Fixed - Fixed the ugly checkboxes - Misc bugfixes and crash fixes. ## [1.7.0+9] - 2019-10-28 ### Added - Re-add the Crafter and autocrafting. ### Fixed - Misc bugfixes and crash fixes. ## [1.7.0+8] - 2019-10-27 ### Added - Re-added the Constructor. - Re-added the Destructor. - Re-added the Disk Manipulator. - Re-added the Portable Grid. ## [1.7.0+7] - 2019-10-22 ### Fixed - Fixed a crash that can happen when opening a world. ## [1.7.0+6] - 2019-10-22 ### Added - Re-added the Network Transmitter (not cross dimensional yet). - Re-added the Network Receiver. - Re-added the Relay. - Re-added the Detector. - Re-added the Security Manager. - Re-added the Interface. - Re-added the Fluid Interface. - Re-added the Wireless Transmitter. - Re-added the Storage Monitor. - Re-added the Wireless Grid. - Re-added the Wireless Fluid Grid. ### Fixed - Misc bugfixes and crash fixes. ## [1.7.0+5] - 2019-10-17 ### Added - Re-added the External Storage. - Re-added the Importer. - Re-added the Exporter. ### Removed - Cutting Tool (you may get a Forge warning about that one, it's safe to ignore). - The "compare nbt" side button, replaced it with "exact mode". ## [1.7.0+4] - 2019-10-15 ### Added - Re-added all the storage blocks. - Re-added JEI integration. ### Fixed - Misc bugfixes and crash fixes. ## [1.7.0+3] - 2019-10-12 ### Added - Re-added the Crafting Grid. - Re-added the Pattern Grid. - Re-added the Fluid Grid. - Re-added Optifine compatibility. ## [1.7.0+2] - 2019-10-10 ### Added - More config values. ### Fixed - Misc bugfixes and crash fixes. ### Removed - Free dirt every 10 ticks. ## [1.7.0+1] - 2019-10-09 ### Added - Re-added the Controller. - Re-added the Disk Drive. - Re-added the Grid. ## [1.6.16] - 2020-04-26 ### Fixed - Fixed erroring controller tile entity. - Fixed Inventory Tweaks sorting not respecting locked slots. - Fixed OpenComputers driver voiding excess fluids. - Fixed being able to move wireless items in inventory. ### Changed - Updated Russian translation. ## [1.6.15] - 2019-07-21 ### Fixed - Fixed recipes with more than 1 bucket of fluid not transferring from JEI. - Fixed oredict crafting patterns redefining recipes. - Fixed Portable Grids not keeping their enchantments when placed. - Fixed JEI hotkeys not working on fluid filter slots. - Fixed crash when opening Crafter Manager with FTB Quests installed. - Fixed a bug where the container slots weren't synced when opening a Grid. ### Changed - Shortened crafting text for the Russion translation to fix Grid overlays. - GregTech Community Edition Wires and Machines are now banned from rendering on Refined Storage patterns because they are causing crashes. ## [1.6.14] - 2019-03-23 ### Fixed - Fixed server crash ## [1.6.13] - 2019-03-23 ### Added - Added keybindings to open wireless items. The default one set to open a Wireless Crafting Grid from Refined Storage Addons is CTRL + G. - Added Grid quantity formatting for item counts over 1 billion. ### Changed - Updated German translation. - Updated Chinese translation. - The Constructor and Destructor now interacts with the world using their owner's profile. ### Fixed - Fixed Interface with Crafting Upgrade being stuck if an earlier item configuration has missing items or fluids. - Fixed wrong item count for oredict patterns. - Fixed autocrafting duplication bug. - Fixed Crafting Pattern not rendering tile entity items like a chest. ## [1.6.12] - 2018-11-28 ### Added - Added a completion percentage to the Crafting Monitor. ### Changed - Updated Russian translation. - Increased the speed of autocrafting. ### Fixed - Fixed External Storage sending storage updates when it is disabled. - Fixed slight performance issue with loading Crafters from disk. - Fixed storage GUIs overflowing on large numbers. ## [1.6.11] - 2018-11-24 ### Fixed - Fixed blocks neighboring a controller breaking when returning from a dimension in a unchunkloaded area. ## [1.6.10] - 2018-11-23 ### Added - Added fluid functions for the fluid autocrafting to the OpenComputers integration. ### Changed - Updated Russian translation. - Slightly increased performance of the External Storage. ### Fixed - Fixed client FPS stalling when using "@" mod search in the Grid. - Fixed client FPS stalling when using "#" tooltip search in the Grid. - Fixed fluid inputs/outputs in the Pattern Grid not being set when you re-insert a Pattern with fluid inputs/outputs. - Fixed bug where the Pattern Grid doesn't update it's output slot when manually configuring a crafting pattern. - Fixed network node scanning allowing multiple controllers in some cases. - Fixed OpenComputers integration not giving back a crafting task instance in the schedule task API. - Fixed OpenComputers integration causing log spam when getting processing patterns. - Fixed OpenComputers voiding items with extract item API when there is no inventory space. - Fixed CraftingTweaks buttons resetting sometimes in the Crafting Grid. - Fixed Refined Storage jars not being signed. - Fixed crafting task stalling when there's not enough space in the inventory. - Fixed another duplication bug with a disconnected Crafting Grid. - Fixed oredict mode in autocrafting not working at all. ### Removed - Removed getMissingItem. - Removed the Interdimensional Upgrade, Network Transmitters are now cross dimensional by default. - Removed the per block FE cost of the Network Transmitter, it draws a fixed amount of FE/t now. ## [1.6.9] - 2018-10-27 ### Changed - You can now interact with the fluid container input slot in the Fluid Interface. ### Fixed - Fixed OpenComputers "unknown error" when using extract item API. - Fixed client FPS stuttering when opening a Crafting Grid. - Fixed rare Grid crashing issue. ## [1.6.8] - 2018-10-20 ### Fixed - Fixed Ender IO incompatibility. ## [1.6.7] - 2018-10-19 ### Changed - The Processor Binding recipe now only gives 8 items instead of 16. ### Fixed - Fixed the Raw Processor recipes not taking oredicted silicon. - Fixed the Processor Binding recipe not taking oredicted slimeballs. ## [1.6.6] - 2018-10-18 ### Added - Added new Crafter modes: ignore redstone signal, redstone signal unlocks autocrafting, redstone signal locks autocrafting and redstone pulse inserts next set. - Added a config option to configure the autocrafting calculation timeout in milliseconds. - Added throttling for network devices that can request autocrafting. ### Changed - Renamed Cut Processors to Raw Processors and those are now made with Processor Binding instead of a Cutting Tool. - You can no longer start a crafting task if it has missing items or fluids. - 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. - 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. ### Fixed - Fixed an autocrafting bug where it crashed when external inventories couldn't be filled. - Fixed a duplication bug with a disconnected Crafting Grid. - Fixed oredict autocrafting sometimes reporting that a craftable item is missing. - Fixed fluid autocrafting without item inputs locking when there's not enough space for the fluids. - Fixed Grid "last changed" date not changing when using clear button or JEI transfer. - Fixed a duplication bug when pressing clear on a Wireless Crafting Grid from Refined Storage Addons. - Fixed a duplication bug with autocrafting and External Storages. - Fixed Crafting Manager displaying wrong name for chained crafters connected to some blocks. - Fixed crafting task losing internal buffer when network runs out of energy. ### Removed - Removed handling of reusable items in autocrafting, to avoid problems. ## [1.6.5] - 2018-09-11 ### Changed - The Pattern Grid in fluid mode now supports up to 64 buckets in the input and output processing slots. ### Fixed - Fixed Refined Storage silicon's oredict entry being registered too late. - Fixed duplication bug with filter slots. ## [1.6.4] - 2018-09-02 ### Changed - Rewrote autocrafting again, bringing performance up to par with other autocrafting mods. - Autocrafting now reserves items and fluids in an internal inventory to avoid having the storage network steal stacks required for autocrafting. - Reworked the Crafting Monitor to be more condensed and more clear. ### Fixed - Fixed not being able to craft upgrades that require enchanted books. - Fixed quick jittering of the Grid and Crafting Monitor when opening them because the tabs appear. ### Removed - Removed left / right click functionality on filter slots to increase / decrease the amount, replaced that functionality with a dialog. ## [1.6.3] - 2018-08-02 ### Added - Re-added a single mode Wrench that can rotate blocks and break Refined Storage covers. ### Fixed - Fixed crash with Wireless Fluid Grid. - Fixed Reborn Storage crafting being slower than normal. ## [1.6.2] - 2018-07-30 ### Fixed - Fixed Grid searching not working. ## [1.6.1] - 2018-07-30 ### Added - Added fluid autocrafting. - Added Crafting Upgrade support for fluids on the Exporter, Constructor and Fluid Interface. - Added config option to hide covers in the creative mode tabs and JEI. ### Changed - The Portable Grid now supports fluid disks. - Filters now support fluids and can be inserted in the Fluid Grid. - You can now keep fluids in stock by attaching a External Storage in fluid mode to a Fluid Interface with a Crafting Upgrade. - You can now specify the amount to export in the Fluid Interface. - Updated Russian translation. - Overhauled and updated German translation. - The Crafting Upgrade no longer schedules requests when there are items or fluids missing. - Made the Crafting Preview window bigger. ### Fixed - Fixed crash log when opening Pattern Grid GUI. - Fixed being able to put non fluid containers in Fluid Interface input slot. - Fixed Grid filters not updating Grid. ### Removed - Removed "emit signal when item is being autocrafted" option in the Detector. ## [1.6.0] - 2018-07-20 ### Added - Added the Cutting Tool. - Added covers. - 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. - 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. - Added config option to configure controller max receive rate. - Added config option to configure energy capacity of Refined Storage items. - Added config option to change Reader / Writer channel energy capacity. - Added a fully charged regular Controller to the creative menu. - Added a missing config option for Crafter Manager energy usage. - Added support for Disk Drive / Storage Block storage and capacity to OC integration. - Added "Search box mode" button to the Crafter Manager. ### Changed - Renamed "Printed Processors" to "Cut Processors". - Rewrote autocrafting. - Rewrote network energy storage. - The Controller item now shows a durability bar for the energy. - You can no longer put a Filter in filter slots to gain additional filter slots. - You can now re-insert Processing Patterns in the Pattern Grid and have the inputs and outputs be completed. - 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. - The Portable Grid no longer exposes a inventory for crossmod interaction, due to performance issues. - The Crafting Monitor is now resizable and its size can be configured (stretched, small, medium, large). - The Crafting Monitor now splits its tasks over tabs. - 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). - The Importer now skips over empty slots. - The Exporter now round-robins over every configured item or fluid to export instead of exporting them all at once. - Updated Russian translation. - Autocrafting tasks that take longer than 5 seconds to CALCULATE (NOT execute) are automatically stopped to avoid server strain. - Changed fluid storage progression to be 64k - 256k - 1024k - 4096k. - Made all IO blocks have a blacklist instead of a whitelist by default. ### Fixed - Fixed bug where pattern was recipe pattern was creatable when there was no recipe output. - Fixed a crash when breaking an Ender IO conduit with the Destructor. - Fixed bug where storage disks in Portable Grids could be moved into themselves. - Fixed the Crafter crashing when opening it while connected to a Primal Tech Grill or Kiln. - Fixed bug where Crafting Upgrade on Interface kept too many items in stock. - Fixed bug where External Storage could only handle 1 fluid inventory per block. - Fixed shift clicking a created pattern going into Grid inventory. - Fixed crash when moving a wireless item with the number keys. - Fixed bug where item storage tracker didn't save sometimes. - Fixed bug where External Storage doesn't detect new inventory when rotating. - Fixed JEI recipe transferring in Pattern Grid allowing non-processing recipes in processing mode and vice-versa. - Fixed using Interfaces for minimum stock levels failing when requester is also an Interface. - Fixed ItemZoom incompatibility in Grid and crafting preview window. - Fixed shift clicking upgrades into Interface making upgrades go to import slots. - Fixed duplication glitch with storages. - Prevent accidental Grid scrollbar click after clicking JEI recipe transfer button. ### Removed - Removed Regulator mode in the Exporter. - Removed MCMultiPart integration. - Removed Project E integration. - Removed blocking mode in autocrafting. - Removed the Wrench. - Removed "void excess items or fluids" functionality on storages. - Removed the Solderer. - Removed "compare oredict" buttons on Exporter, Importer, etc. - Removed ConnectedTexturesMod integration for fullbright textures, RS now has fullbright textures natively. - 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. ## [1.5.34] - 2018-05-22 ### Added - Added OR search operator to the Grid with "|". - Added new `getPattern(stack:table)` function for OpenComputers integration. ### Changed - Empty patterns can no longer be inserted in the pattern result slot in the Pattern Grid with hoppers. - `getPatterns()` now only returns all the outputs, this to limit memory usage in OpenComputers (only affects OC integration). - Allow crafters to be daisy-chained. ### Fixed - Fixed repeated key events not getting handled in some cases. ## [1.5.33] - 2018-04-22 ### Added - Added Crafter Manager. ### Changed - Patterns in the Crafter slots now automatically render the output without pressing shift. - Increased Grid performance. - Various internal refactors. ### Fixed - Fixed Disk Manipulator not extracting items. - Fixed filter slots not caring about max stack size. - Fixed model warning about Portable Grid. - Fixed crash when autocompleting Ender IO recipes from JEI. - Fixed Grid not always using all combinations when using JEI autocompletion. ## [1.5.32] - 2018-03-08 ### Added - Added Spanish translation. ### Changed - Changed stack quantity of craftable items from 1 to 0 to fix Quantity Sorting. - Changed fluid stack amount to not display "0" anymore. - 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). ### Fixed - Fixed issue where the Pattern Grid can only overwrite patterns when blank ones are present. - Fixed not being able to extract half a stack of items with max stack size 1 in Grid when using right click. - Fixed 2 same stacks using capabilities without NBT tag not treated equal. - Fixed NBT/metadata check on exporting in an Interface. - Fixed Disk Manipulator being stuck on unemptiable, non-empty disks. - Fixed orientations of the Portable Grid. - Fixed crafting event in Crafting Grid being fired twice. - Fixed a crash when the Constructor tries to place a block when a multipart is attached to it. - Fixed an autocrafting crash. - Attempted to fix FPS drop on Grid sorting. ## [1.5.31] - 2017-12-31 ### Changed - Storage disk and block stored and capacity counts are formatted now in the tooltip. - Improved the "cannot craft! loop in processing..." error message. - Made the Disk Manipulator unsided (inserting goes to insert slots and extracting from output slots). ### Fixed - Fixed error logs when toggling the Pattern Grid from and to processing mode. - Fixed pattern slots in Crafters not being accessible. - Fixed rare Grid crash. - Fixed OpenComputers cable showing up in Grid as air. ## [1.5.30] - 2017-12-24 ### Fixed - Fixed crashing bug when MCMultiPart is not installed. ## [1.5.29] - 2017-12-23 ### Changed - Update Forge to 2577 (minimum Forge version required is now 2555 for MC 1.12.2). ### Fixed - Fixed bug where MCMP multiparts were blocking RS network connections. - Fixed Reader/Writers for energy extracting energy when not needed. ## [1.5.28] - 2017-12-13 ### Changed - Item Reader/Writers can now store 16 stacks. - Fluid Reader/Writers can now store 16 buckets. - Energy Reader/Writers can now store 16000 FE. ### Fixed - Fixed Writers not pushing energy. ## [1.5.27-beta] - 2017-12-09 ### Fixed - Fixed non-oredict patterns not consuming resources. ## [1.5.26-beta] - 2017-12-09 ### Added - Added Funky Locomotion integration. ### Fixed - Fixed Exporter in Regulator Mode not regulating properly when same item is specified multiple times. - Fixed air appearing in Grid. - Fixed config categories not correctly appearing in ingame config GUI. - Fixed craftable items showing "1 total" if not stored in system in Grid. - Minor fixes to autocrafting. ### Removed - Removed "detailed" Grid view type variant, made detailed tooltips a config option instead. ## [1.5.25] - 2017-11-28 ### Fixed - Fixed not being able to autocraft different Storage Drawers' wood drawers. - Fixed not being able to autocraft certain Modular Routers items. - Fixed last modified date not being sent when extracting from an External Storage. ## [1.5.24] - 2017-11-26 ### Added - Added "Last modified" sorting option in the Grid. - Added a "detailed" variant for every Grid view type option, to disable the modified information on the tooltip. ### Changed - The Grid now displays last modified information (player name and date) and size on tooltips of stacks. ### Fixed - Fixed Exporter with Stack Upgrade not working correctly in Regulator Mode. - Fixed crash with the Constructor. - Fixed patterns being able to crash when no inputs are provided. - Fixed possible crash with network scanning. ### Removed - Removed craft-only mode for the Exporter. ## [1.5.23] - 2017-11-13 ### Fixed - Fixed duplication bug with autocrafting. - Fixed Fluid Interface with Stack Upgrade not exporting fluids. - Fixed fluids in Fluid Grid not showing actual mB on tooltip when pressing CTRL + SHIFT. ## [1.5.22] - 2017-11-11 ### Added - Added oredict, blocking, processing, ore inputs access to OpenComputers API. - Added shortcut to clear Grid crafting matrix (CTRL+X). ### Changed - The Crafter can now only store 1 stack size pattern per slot. - You can now re-insert a Pattern in the pattern output slot in the Pattern Grid to modify an existing pattern. - The Refined Storage jar is now signed. - Updated Chinese translation. ### Fixed - Fixed not being able to use JEI R and U keys on Grid with tabs. - Fixed lag when opening a Grid with lots of items by offloading the grid sorting to another thread. - Performance improvement when adding patterns to the network. ## [1.5.21] - 2017-10-19 ### Changed - Updated Portuguese (Brazilian) translation. ### Fixed - Fixed crash with External Storage. - Fixed stack-crafting in the crafting grid (crafting table) causing lag on a dedicated server. - Fixed cable blocks, Wireless Transmitter, Detector and Portable Grid acting as full blocks (being able to place torches on them etc). ## [1.5.20] - 2017-10-09 ### Fixed - Restore MC 1.12.0 compatibility. ## [1.5.19] - 2017-10-08 ### Changed - Updated Forge to 2493 (MC 1.12.2). ### Fixed - Fixed Refined Storage blocks requiring a pickaxe to be broken. - Fixed Grid GUI crash. - Fixed device names overflowing Controller GUI. - Fixed high CPU load when Refined Storage GUIs are open. - Fixed not being able to extract Mekanism tanks and bins from the Grid. - Fixed not being able to craft Immersive Engineering Revolver. - Fixed rare bug when server crashes on startup due to network node not existing. ## [1.5.18] - 2017-09-08 ### Added - Added Project E integration for the External Storage on the Transmutation Table. - Added Project E integration for the energy values of Solderer items. - Added support for more than 4 grid tabs in the Grid by putting filters IN filters. - Added protection for other mods causing crashes when drawing an item or display name. ### Changed - Reader and Writer blocks now face the block you're placing it on, not the player. - 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. - The Fortune Upgrade doesn't use NBT anymore to store the fortune level. ### Fixed - Fixed network not disconnecting when Controller is broken. - Fixed bug where when multiple Fortune Upgrades are inserted, it chooses the first Fortune Upgrade instead of the highest one. - Fixed some translations having too big "Craft" text. - Fixed crash with GUI when toggling the Grid size quickly. - Fixed scrollbar not scrolling correctly when clicked with mouse when grid tabs are visible. - Fixed Reader and Writers GUIs still displaying channels even if not connected. - Fixed Solderer resetting progress when the inventory changes. ## [1.5.17] - 2017-08-19 ### Added - Re-added support for OpenComputers. ### Fixed - Fixed crash with Grid. ## [1.5.16] - 2017-08-09 ### Fixed - Fixed crash when placing a Controller. - Fixed crash when configuring an Exporter. - Fixed Refined Storage not running in MC 1.12 and only on MC 1.12.1. ## [1.5.15] - 2017-08-09 ### Added - Added InventoryTweaks Grid sorting. - Added InventoryTweaks inventory sort ability in Refined Storage GUIs. - Added CTM integration for Disk Manipulator. ### Changed - Updated Forge to 2444 (MC 1.12.1). ### Fixed - Fixed possible rare dupe bug with Importer. - Fixed Shulker Box dupe bug with Destructor. - Fixed Grid crash with search history. - Fixed Grid crash with search field. - Fixed External Storage not working without Storage Drawers. - Fixed External Storage not calculating max stack size in the calculation of it's capacity display in the GUI. - Fixed Refined Storage not drawing small text correctly with Unicode font. - Fixed dupe bug with External Storage connected to an item handler. ## [1.5.14] - 2017-08-03 ### Added - 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. - Added CTM integration. ### Changed - Updated Forge to 2426. - Updated French translation. ### Fixed - Fixed more crashes relating to scrollbar in GUIs. - Fixed crash with Detector. - Fixed bug where pattern create button wasn't visible when grid tabs were selected. - Fixed performance issue with Controllers turning off and on and Interfaces. - Fixed Interfaces exposing network inventory don't hide storages that are disconnected. ## [1.5.13] - 2017-07-20 ### Fixed - Fixed Wireless Fluid Grid not using up energy. - Fixed Wireless Crafting Monitor remaining in network item list. ## [1.5.12] - 2017-07-17 ### Added - Added additional API for grids. ### Changed - The Network Transmitter now uses 1 FE/t per block instead of 4 FE/t. ## [1.5.11] - 2017-07-16 ### Fixed - Fixed not being able to smelt quartz into silicon. - Fixed Grid extracting wrong enchanted books. ## [1.5.10] - 2017-07-15 ### Fixed - Fixed crash relating to MCMP. ### Changed - Converted Solderer recipes to JSON. - Implemented controller update throttling, should fix lag issues with controllers that constantly turn off and on. ## [1.5.9] - 2017-07-10 ### Fixed - Fixed not being able to extract anything when connecting an External Storage to Storage Drawers. ## [1.5.8] - 2017-07-08 ### Changed - Updated Forge to 2400. - Updated Storage Drawers API. - Autocrafting can now fill water bottles with water from the fluid storage - regular bottles or pattern for regular bottles are required. ### Fixed - Fixed bug where disks have to be re-inserted in the Disk Drive in order to work again after rejoining a chunk. - Fixed bug where items inserted in Storage Drawers through External Storage with a Drawer Controller wouldn't respect drawer priority rules. - Fixed crash on server when getting an advancement. ### Removed - 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. ## [1.5.7] - 2017-07-04 ### Added - Added advancements. ### Changed - Exposed pattern inventory for Pattern Grid. ### Fixed - Fixed crashes relating to scrollbar in GUIs. ## [1.5.6] - 2017-06-29 ### Changed - Updated Forge to stable 2387. ### Fixed - Fixed bug where players couldn't place regular blocks next to secured networks. ### Removed - Removed Processing Pattern Encoder, that functionality is now available in the Pattern Grid. ## [1.5.5-beta] - 2017-06-25 ### Changed - Updated Forge to 2363. ## [1.5.4-beta] - 2017-06-24 ### Fixed - Fixed External Storage crashing. - Fixed crash when node data mismatches between world and dat file. ## [1.5.3-beta] - 2017-06-24 ### Added - The Portable Grid now exposes an inventory for interaction with other mods or vanilla. - The Interface now exposes the entire storage inventory (if no slots are set for exporting) for interaction with other mods or vanilla. ### Changed - Updated Forge to 2359. - Updated MCMultiPart to 2.2.1. ### Fixed - Fixed Solderer crashing. - Fixed Solderer being able to work with insufficient ingredients. - Fixed Interface extracting from itself when trying to keep items in stock. - Fixed Quartz Enriched Iron recipe only giving 1 instead of 4. - Fixed Debug Storage disks not working correctly. - Fixed Disk Drive giving incorrect capacity for creative and debug storage disks. ### Removed - The Relay now reacts instantly to a redstone signal again, removed throttling for it. ## [1.5.2-beta] - 2017-06-20 ### Fixed - Fixed a bug where loading nodes would abort when a single node has an error while reading. - Fixed Filters not persisting correctly in Portable Grid. ## [1.5.1-beta] - 2017-06-20 ### Added - Re-added MCMultiPart support. - Added back crafting recipes. ### Changed - Updated Forge to 2340. - Changed Grid recipe. - Changed Crafting Monitor recipe. ### Fixed - Fixed Filters not persisting correctly in Wireless Grid and Wireless Crafting Monitor. - Fixed Disk Drive recipe not using ore dictionary for chest. - Fixed crash when getting tooltip for grid item. ### Removed - Removed Tesla integration. - Removed RS energy units, the entire mod is powered with Forge Energy now. ## [1.5.0-alpha] - 2017-06-14 ### Added - Port to Minecraft 1.12. - The Portable Grid now doesn't despawn anymore when dropped in the world. ### Fixed - Fixed bug where oredict autocrafting didn't work in some cases. ### Removed - Removed MCMultiPart support (will be re-added as soon as MCMultiPart for MC 1.12 is available). - Removed OpenComputers support (will be re-added as soon as OpenComputers for MC 1.12 is available). - Removed crafting recipes, until Forge adds the recipe system back. ## [1.4.20] - 2017-07-15 ### Fixed - Fixed crash relating to MCMP. ## [1.4.19] - 2017-07-15 ### Added - Implemented controller update throttling, should fix lag issues with controllers that constantly turn off and on. ### Fixed - Fixed bug where players couldn't place regular blocks next to secured networks. - Fixed crashes relating to scrollbar in GUIs. - Fixed bug where disks have to be re-inserted in the Disk Drive in order to work again after rejoining a chunk. ## [1.4.18] - 2017-06-24 ### Fixed - Fixed Solderer crashing. - Fixed Interface extracting from itself when trying to keep items in stock. - Fixed Solderer being able to work with insufficient ingredients. - Fixed Disk Drive giving incorrect capacity for creative and debug storage disks. - Fixed External Storage crashing. - Fixed crash when node data mismatches between world and dat file. ### Removed - The Relay now reacts instantly to a redstone signal again, removed throttling for it. ## [1.4.17] - 2017-06-20 ### Fixed - Fixed Filters not persisting correctly in Wireless Grid, Wireless Crafting Monitor and Portable Grid. - Fixed Disk Drive recipe not using ore dictionary for chest. - Fixed a bug where loading nodes would abort when a single node has an error while reading. ## [1.4.16] - 2017-06-14 ### Added - The Portable Grid now doesn't despawn anymore when dropped in the world. ### Fixed - Fixed bug where oredict autocrafting didn't work in some cases. ## [1.4.15] - 2017-06-14 ### Changed - Updated Storage Drawers API, fixes crashes. ## [1.4.14] - 2017-06-13 ### Fixed - Fixed Solderer not accepting books made in anvil. ## [1.4.13] - 2017-06-13 ### Added - The Portable Grid now has an indicator whether it's connected or disconnected and shows the disk. ### Fixed - Fixed Portable Grid model. - Fixed ore dictionary causing problems with Solderer. - Fixed ore dictionary items not showing up in JEI for the Solderer. ### Removed - Removed Quartz Enriched Iron ore dictionary entry. ## [1.4.12] - 2017-06-10 ### Added - Added Korean translation. - Implemented block update throttling when network turns on and off. ### Changed - Updated Forge to 2315. - Updated JEI to 4.5.0. - You can now shift click items from the Grid crafting slots to the player inventory when the Grid is disconnected. ### Fixed - Fixed error logs when watching a Controller when a network changes. ### Removed - Removed Collosal Chests integration. ## [1.4.11] - 2017-06-05 ### Added - Added support for External Storage on Interfaces and other Refined Storage blocks, so you can keep items in stock easier. - You now have to sneak to place the Portable Grid in the world. ### Changed - The Machine Casing now requires 1 piece of stone in the middle. - Changed recipe of Disk Drive to no longer require a Solderer. - Changed recipe of Interface to no longer require a Basic Processor, but a Machine Casing instead. ### Fixed - Fixed bug where storages that are removed remain visible. - Fixed bug where the GUI didn't close when a block is broken, causing a dupe bug with the Portable Grid. ### Removed - Removed debug log configuration option, as it's no longer needed. - Removed "autocraft on redstone signal" option in the Crafter, use an External Storage in combination with an Interface with the Crafting Upgrade instead. ## [1.4.10-beta] - 2017-05-25 ### Changed - Improved performance of network scanning. ### Fixed - Fixed crash when attempting to get direction of a node. - Fixed bug where some network parts don't want to connect to the storage system. ## [1.4.9-beta] - 2017-05-24 ### Fixed - Fixed bug where inventory data was lost sometimes upon opening the world. ## [1.4.8-beta] - 2017-05-24 ### Fixed - Fixed missing config categories in ingame config. - Fixed Controller not working anymore after changing redstone setting. - Fixed crash when placing or destroying network blocks. ## [1.4.7-beta] - 2017-05-23 ### Added - 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. ### Fixed - Fixed bug where Portable Grid would dupe in inventory. - Worked around an autocrafting bug to prevent crashes. ## [1.4.6-beta] - 2017-05-17 ### Changed - Performance improvement to network scanning. ### Fixed - Fixed Wrench opening GUIs while performing action. - Fixed client Grid GUI clearing and causing crashes after starting an autocrafting request. ### Removed - Removed debug output from v1.4.5. ## [1.4.5-beta] - 2017-05-14 ### Added - Added Portable Grid. - Added OpenComputers integration. ### Changed - Updated Forge to 2296. - Removed ticking tile entities, every tile entity in RS is non-ticking now. ### Fixed - Fixed Crafting Tweaks buttons positioned wrongly. - Fixed Crafting Tweaks keybindings interfering with RS keybindings. - Fixed crash when updating storages. - Fixed no tooltips for fluid filter slots. - Fixed Disk Manipulator in fluid mode not showing fluids. - Fixed dupe bug in the Interface. ## [1.4.4-beta] - 2017-04-27 ### Changed - Updated Forge to 2284. ### Fixed - Fixed Disk Manipulator crashing due to empty stack. - Fixed issue where empty stacks show up in the system. - Fixed Storage Monitor not respecting security settings. ## [1.4.3-beta] - 2017-04-22 ### Added - Display progress bar on JEI recipes for the Solderer. ### Changed - Updated Forge to 2282. - Updated JEI version. - Updated MCMultiPart version. - You can now shift click Grid Filters into a Grid instead of manually inserting them. - You can now use up and down arrows to scroll through Grid search history. - Shift clicking patterns in the Pattern Grid now puts the patterns in the pattern slot. - Storage Monitors don't render any quantity text when no item is specified to monitor anymore. - The Solderer inventory isn't sided anymore. - Small performance improvement: only sort the storages when needed. ### Fixed - Fixed bug where disks in Disk Drive didn't respect access type or void excess stacks option. - Fixed crash in Disk Manipulator. - Fixed oredict not working. - Fixed Grid crash. - Fixed Fluid Grid not formatting large quantities correctly. ## [1.4.2-beta] - 2017-04-01 ### Added - Implemented support for the Forge update JSON system. - Added integration for MCMultiPart, this is an optional dependency. - You can now specify more items to export, import, filter, etc. by inserting the Filter item. - Made the keybinding to focus on the Grid search bar configurable. ### Changed - Updated Forge to 2261. - The Detector no longer outputs a strong redstone signal. - Fire event on completion of an autocrafting task. - Fire "player crafting" event when shift clicking in the grid. ### Fixed - Fixed a crash with the Constructor. - Fixed Crafting Pattern model. - Fixed Quartz Enriched Iron and the block form of it not having an oredictionary entry. - Fixed crash in storage cache. - Fixed slow oredict comparisons causing TPS lag. - Fixed controller model warning during launch. - Fixed not rendering some tooltips correctly. - Fixed crash with External Storage. - Fixed Interface duping items on extract-only storages. - Fixed controls menu showing unlocalized text for Refined Storage keybindings. - Autocrafting bugfixes. - Improved memory usage of some models. - Performance improvements related to storage inserting and extracting. ### Removed - Removed support for the Deep Storage Unit API. ## [1.4.1-beta] - 2017-02-19 ### Added - Added Storage Monitor. ### Changed - Updated Forge to 2232. ### Fixed - Fixed Processing Pattern Encoder and Security Manager recipes not supporting oredict workbench and chest. - Fixed network nodes not respecting redstone mode. - Fixed "Clear" and "Create Pattern" buttons not working correctly when using Grid Filter tabs. - Fixed Wrench in Dismantling Mode voiding Storage Block contents. - Fixed OPs not having global permissions on secured storage systems. - Fixed crash when Destructor tries to break secured network block. - Fixed Fluid Interface not dropping inventory contents. - Fixed Disk Manipulator crash. ## [1.4.0-beta] - 2017-02-06 ### Added - Added Security Manager. - Added Security Card. - Added Wireless Fluid Grid. - Added craft-only toggle to Exporter. - Added Reader. - Added Writer. - Added blocking mode to patterns in autocrafting. - Added Grid size toggle (stretched, small, medium, large). - Added dismantling mode to the Wrench. - Added Block of Quartz Enriched Iron. - Added integration for Collosal Chests for the External Storage, Importer and Exporter improving performance. - Added filtering slots for the Crafting Monitor. - Added way to hide tasks created in an automated way in the Crafting Monitor. - Added Grid sorting by ID. - Added Solderer particles. - Added ore dictionary Grid filter (use `$` as prefix like in JEI). ### Changed - You can now bind multiple crafters with the same pattern to machines, to spread or balance out autocrafting. - Fluid Grid now first tries to get buckets from your inventory instead of the storage. - Updated Forge to 2226. - Updated Chinese translation. - Converting blocks instead of ingots to Printed Processors is now a little faster. - The Stack Upgrade in a Constructor in item dropping mode will drop stacks of items at a time. - Ignore damage for damageable items when transferring into crafting grid. - Ignore tags from given items when transferring into crafting grid. - Removed sidedness from fluid interface. - Using tab in a grid that isn't in autoselected mode will focus on the search box. - Exposed the Network Card inventory of the Network Transmitter so other tiles can interact with it. - Increased size of Detector textbox. - Handle breaking and placing blocks better for Constructor and Destructor. - Pressing shift while starting a crafting task will skip the crafting preview. ### Fixed - Fixed Regulator mode not working. - Fixed Fluid Interface still being sided. - Fixed Constructor not working on Botania flowers. - Fixed Wireless Transmitter working even if it was disabled with redstone mode. - Fixed Solderer not accepting books created in an Anvil. - Fixed bug where network machines stopped working on chunk borders. - Fixed memes not working. - Fixed External Storage crashes. - Fixed Constructor in liquid mode being able to place fluids <1000 mB. - Fixed Solderer recipe conflicts, allowing for easier automation. - Fixed stack upgrades not working in exporter when stack size is 16. - Fixed crash when rotating External Storage. - Fixed disk textures not working on latest Forge. - Fixed crash when placing head with Constructor. - Autocrafting bugfixes. - Made sure External Storage always has the correct inventory in world. ## [1.3.5-alpha] - 2016-12-14 ### Added - Added regulator mode to Exporter. ### Changed - Updated French translation. ### Fixed - Fixed TPS lag on very large crafting tasks. - Fixed not being able to use autocrafting on some EnderIO items. - Fixed server crash with ore dictionary checks. - Fixed Controller not using energy. - Fixed dupe bug when inserting bucket in Fluid Grid. - Fixed not being able to start autocrafting for storage disks. - Fixed oredict button not having the correct position on a small resolution. - Fixed Constructor not using Crafting Upgrade when in item dropping mode. ## [1.3.4-alpha] - 2016-12-10 ### Added - Added option to check for oredict in the Grid Filter. - Added option to use a mod filter in the Grid Filter. - Added option to use a whitelist or blacklist in the Grid Filter. - Added Grid tabs using Grid Filters. - Added configuration option to enable large fonts in Grid. ### Changed - The Grid now resizes based on screen size (max rows can be configured). - Made Solderer tooltip less big. - Made the Interface sideless, you can just insert or extract from any side. ### Fixed - Fixed bug with opening a network item with food in offhand. - Fixed not respecting "Extract only" option for storages. - Fixed a few autocrafting bugs. - Fixed a crash with the Disk Manipulator. ## [1.3.3-alpha] - 2016-12-06 ### Changed - Updated Forge to 2188. ### Fixed - Fixed not being able to start a crafting task. ## [1.3.2-alpha] - 2016-12-04 ### Fixed - Fixed being able to exceed max stack size while shift clicking. - Fixed Wrench clearing NBT data when reset causing problems with Morph O Tool. - Fixed client crash when placing network blocks. ## [1.3.1-alpha] - 2016-12-04 ### Changed - Updated Forge to 2180. - Made Upgrades stackable. ### Fixed - Fixed Disk Drive not noticing a Storage Disk being shift clicked out of the GUI. ## [1.3.0-alpha] - 2016-12-03 ### Added - Port to Minecraft 1.11. ### Removed - Removed RF support, use Forge Energy instead. - Removed IC2 support. - Removed MCMultiPart support (will be re-added as soon as MCMultiPart for MC 1.11 is available). ## [1.2.26] - 2017-06-10 ### Fixed - Fixed Interface duping items on extract-only storages. - Fixed calculating crafting resources for more than 9 unique items, for addon mods. ## [1.2.25] - 2017-03-25 ### Changed - Fire event on completion of an autocrafting task. - Fire player crafting event when shift clicking in the grid. - Allow INodeNetwork instances to return an ItemStack for display in Controller GUI. ## [1.2.24] - 2017-03-18 ### Changed - Made the keybinding to focus on the Grid search bar configurable. ### Fixed - Autocrafting bugfixes. ## [1.2.23] - 2017-03-11 ### Added - Implemented support for the Forge update JSON system. ### Changed - The Detector no longer outputs a strong redstone signal. ### Fixed - Fixed crash in storage cache. - Fixed Crafting Pattern model. - Fixed Constructor not working on Botania flowers. - Fixed Disk Manipulator crash. - Fixed slow oredict comparisons causing TPS lag. ## [1.2.22] - 2017-02-19 ### Fixed - Fixed recipe for Processing Pattern Encoder not using oredictionary for the workbench. - Fixed Fluid Interface not dropping inventory contents. - Fixed glitchy upgrade recipes in the Solderer. ## [1.2.21] - 2017-02-07 ### Fixed - Fixed crash when placing head with Constructor. ## [1.2.20] - 2017-02-02 ### Added - Added Solderer particles. - Added Grid sorting by ID. ### Fixed - Fixed client side crash with cables. ## [1.2.19] - 2017-02-01 ### Added - Added integration for Collosal Chests for the External Storage, Importer and Exporter improving performance. ### Changed - Updated cable part back texture and Construction and Destruction Core textures. - Updated Forge to 2221. - Updated Chinese translation. - Exposed the Network Card inventory of the Network Transmitter so other tiles can interact with it. - Increased size of Detector textbox. - Autocrafting bugfixes. - Handle breaking and placing blocks better for Constructor and Destructor. ### Fixed - Fixed stack upgrades not working in exporter when stack size is 16. - Fixed crash when rotating External Storage. - Fixed disk textures not working on latest Forge. ## [1.2.18] - 2017-01-22 ### Changed - Fluid Grid now first tries to get buckets from your inventory instead of the storage. - Performance improvements with oredict autocrafting. ### Fixed - Fixed client side crash with cable. - Fixed client side crash with disk drive. - Fixed crash with external storage in fluid mode. ## [1.2.17] - 2017-01-12 ### Added - Add Ore Dictionary grid filter (use $ as prefix like in JEI). ### Changed - Ignore damage for damageable items when transferring into crafting grid. - Ignore tags from given items when transferring into crafting grid. - Removed sidedness from fluid interface. - Using tab in a grid that isn't in autoselected mode will focus on the search box. - The Stack Upgrade in a Constructor in item dropping mode will drop stacks of items at a time. ### Fixed - Fixed Constructor in liquid mode being able to place fluids <1000 mB. - Fixed Solderer recipe conflicts, allowing for easier automation. - Fixed machines not connecting with cable after Controller. ## [1.2.16] - 2017-01-04 ### Fixed - Fixed an autocrafting regression. - Fixed crash with External Storage. ## [1.2.15] - 2017-01-03 ### Fixed - Fixed Grid Filter hiding everything when 2 or more items are in it. - Fixed External Storage crash when breaking a connected inventory. - Autocrafting bugfixes. ## [1.2.14] - 2016-12-24 ### Fixed - Fixed server crash. ## [1.2.13] - 2016-12-23 ### Fixed - Fixed memes not working. - Fixed controller causing network rebuild on every neighbor change. - Fixed Wireless Transmitter working even if it was disabled with redstone mode. - Fixed Solderer not accepting books created in an Anvil. - Autocrafting bugfixes. - Made sure External Storage always has the correct inventory in world. ## [1.2.12] - 2016-12-16 ### Changed - Updated French translation. ### Fixed - Fixed TPS lag on very large crafting tasks. - Fixed not being able to use autocrafting on some EnderIO items. - Fixed not being able to start autocrafting for storage disks. - Fixed oredict button not having the correct position on a small resolution. - Fixed Constructor not using Crafting Upgrade when in item dropping mode. ## [1.2.11] - 2016-12-10 ### Added - Added configuration option to enable large fonts in Grid. ### Changed - The Grid now resizes based on screen size (max rows can be configured). - Made the Interface sideless, you can just insert or extract from any side. ## [1.2.10] - 2016-12-09 ### Changed - Made Solderer tooltip less big. ### Fixed - Fixed a crash with the Disk Manipulator. - Fixed not respecting "Extract only" option for storages. - Fixed bug with opening a network item with food in offhand. - Fixed other fluid storages going negative when using void excess fluids option. - A few autocrafting bugfixes. ## [1.2.9] - 2016-12-06 ### Changed - Updated Forge to 2185. ### Fixed - Fixed Wrench clearing NBT data when reset causing problems with Morph O Tool. ## [1.2.8] - 2016-11-30 ### Fixed - Fixed autocrafting bugs. ## [1.2.7] - 2016-11-29 ### Changed - Updated German translation. ### Fixed - Fixed not being able to place disks in Disk Drives on servers. ## [1.2.6] - 2016-11-26 ### Changed - Processing patterns can now insert buckets. ### Fixed - Fixed crash with Exporters in fluid mode. ### Removed - Removed Solderer progress percentage text. ## [1.2.5] - 2016-11-24 ### Added - Added "View Recipes" JEI toggle in Solderer. ### Changed - The Constructor can now place fireworks. - Updated Forge to 2151. ### Fixed - Fixed a bunch of autocrafting bugs. - Fixed Grid search not working correctly. - Fixed items disappearing from Solderer inventory. - Fixed being able to take fluids that have less than 1000 millibuckets filled in Fluid Grid. - Fixed Constructor being able to place fluids that have less than 1000 millibuckets. - Fixed Exporter and Importer not working properly with fluids. - Fixed inserting new stack type with right click in Grid causing a desync. - Fixed Constructor not calling block place event. - Fixed shift clicking non disk items in the Disk Manipulator voiding them. ## [1.2.4] - 2016-11-10 ### Added - Added tooltip search with #. ### Changed - Mod search can now also take mod name instead of just id. ### Fixed - Fixed bug where Disk Manipulator doesn't save disks. - Fixed Disk Drive stored quantity GUI text hovering over other text. - Fixed External Storage being in item and fluid mode at the same time. - Fixed Wrench working when player is not sneaking. - Fixed External Storage cache counting items up when extracting. - Fixed External Storage cache not working properly on Compacting Drawers. ### Removed - Removed ability to put External Storages on Refined Storage network blocks. ## [1.2.3] - 2016-11-06 ### Fixed - Fixed fluid cache updating wrongly. - Fixed Exporter scheduling too many crafting tasks. ## [1.2.2] - 2016-11-05 ### Fixed - Fixed item voiding when exporting to a chest with a storage in Extract Only mode. - Various autocrafting fixes. ## [1.2.1] - 2016-11-05 ### Added - Added Wireless Crafting Monitor (with temporary textures). - Added support for JEI R and U keys in Grids. ### Changed - You can now decompose storage disks if the item count is below zero by any chance. ### Fixed - Fixed crafting upgrade having weird behavior. - Fixed external storage not updating when loading chunk. - Fixed external storage crash. - Fixed weird autocrafting behavior. ### Removed - Removed controller explosions when multiple controllers are connected to the same network. ## [1.2.0] - 2016-11-03 ### Added - Added new autocrafting system. - Added ore dictionary autocrafting. - Added recipe transfer handler for Processing Pattern Encoder. - Added void excess items functionality to storage blocks. - Added config option to configure RS to EU conversion rates. - Added ability to toggle between insert and extract, only insert and only extract mode in storage blocks. - Added Silk Touch Upgrade for Destructor. - Added Fortune Upgrade for Destructor. - Added ore dictionary compare toggle to storage I/O blocks. - Added disk leds to Disk Drive block that shows the disks. - Added disk leds to Disk Manipulator block that shows the disks. - Added Wrench, has two modes: configuration saving / reading mode, and rotation mode. - Stack upgrade in Importer / Exporter in fluid mode and Fluid Interface now transfers 64 buckets at once. ### Changed - Changed storage GUIs. - Changed default EU conversion rate to be 1:8 with RS. - The Constructor can now drop items in the world. - The Constructor can now place skulls. - The Destructor can now pick up items in the world. - Storage disks and storage blocks now don't despawn anymore when dropped in the world. - Grid item and fluid quantity now only rounds to 1 digit after comma. - Items count can no longer overflow, and will max out at the maximum integer value. - Updated Storage Drawers API. - Controller sorts by energy usage in GUI (highest to lowest). - Detector without any filter will detect based on total items or fluids stored. - Limited network transmitter usage to 1000 RS/t. ### Fixed - Fixed lag issues caused by External Storage. - Fixed resetting a stack of patterns yields 1 blank pattern. - Fixed being able to pipe items in the export slots of the Interface. - Fixed Interface being stuck when item isn't accepted in storage. - Fixed items with colored name being uncolored in Grid. - Fixed fluid rendering bugging out side buttons. - Fixed item count going negative when using the Disk Manipulator. - Fixed Storage Drawer quantities not updating properly on Void Drawers. - Fixed Disk Manipulator blocking items transferring in some cases. - Fixed External Storage crafting recipe not supporting ore dictionary chests. - Fixed when shift clicking crafting recipe and inventory is full items are dropping on the ground instead of going in the system. - Fixed glitchy rendering of cable parts in item form. - Fixed Destructor being able to break bedrock. - Fixed External Storage thinking that items are inserted in Extra Utilities Trash Cans. - Fixed Grid quantities being unreadable when using unicode font. - Fixed disconnecting when Storage Disk or Storage Block is too big. ## [1.2.0-beta.8] - 2016-11-03 ### Fixed - More autocrafting issues. ## [1.2.0-beta.7] - 2016-11-03 ### Fixed - More autocrafting issues. - External Storage crashes and TPS lag issues. - Mekanism recipes are autocraftable again. ## [1.2.0-beta.6] - 2016-11-02 ### Fixed - More autocrafting issues. - Oredict autocrafting has been improved. ## [1.2.0-beta.5] - 2016-10-30 ### Fixed - More autocrafting issues. - External Storage TPS lag issues. ## [1.2.0-beta.4] - 2016-10-27 ### Fixed - More autocrafting and TPS issues. ## [1.2.0-beta.3] - 2016-10-25 ### Fixed - More autocrafting issues. ## [1.2.0-beta.2] - 2016-10-24 ### Fixed - Extreme TPS issues while crafting. - Laggy disk drive rendering. ## [1.2.0-beta.1] - 2016-10-23 ### Changed - First beta release for v1.2.0, featuring a new autocrafting system. ## [1.1.3] - 2016-10-07 ### Fixed - Fixed some clients not starting up due to too many Disk Drive model permutations. ## [1.1.2] - 2016-10-03 ### Added - Added recipe transfer handler for Solderer. ### Changed - It is now possible to start a crafting task even if the crafting preview says you can't. ### Fixed - Fixed crash with JEI when changing screens in autocrafting. - Fixed not being able to start autocrafting in other dimensions with Network Transmitter / Network Receivers. - Fixed JEI overlay disappearing now and again. - Fixed Detector hitbox. ## [1.1.1] - 2016-09-28 ### Fixed - Fixed crash on servers. ## [1.1.0] - 2016-09-28 ### Added - New art by CyanideX. - Added crafting preview screen. - Added max crafting task depth. - Added helpful tooltips to Solderer and Processing Pattern Encoder. ### Changed - Every machine now compares on damage and NBT by default. - Updated JEI, fixes crashes. - Detector amount text field doesn't autoselect anymore. ### Fixed - Fixed crash with Disk Manipulator. - Fixed autocrafting not giving back byproducts. ## [1.0.5] - 2016-09-21 ### Added - Importer now takes a Destruction Core, and Exporter a Construction Core. - Added Disk Manipulator. - Added ingame config. - Added the ability to see the output of a Pattern by holding shift. - Exporter in fluid mode and Fluid Interface no longer duplicates fluids that are less than 1 bucket. ### Changed - Changed default Grid sorting type to quantity. - Updated Dutch translation. - Updated Chinese translation. - When a machine is in use by a crafting pattern, inserting of items from other patterns will be avoided. ### Fixed - Fixed crafting a complex item causes the process to flow off the Crafting Monitor's GUI. - Fixed shift clicking from Grid when player inventory is full throwing items in the world. ## [1.0.4] - 2016-09-17 ### Fixed - Fixed lag caused by Crafter. ## [1.0.3] - 2016-09-17 ### Added - Added integration for Forge energy. ### Changed - Solderer now accepts items from any side, allowing easier automation. - Solderer is now intelligent about items in slots, and will only accept an item if it is part of a recipe. - Changed recipe for upgrades in the Solderer, they now just take 1 of the unique item instead of 2, using redstone instead. - Updated to Forge 2088. ### Fixed - Fixed item loading issue. - Fixed fluid autocrafting scheduling too much crafting tasks for buckets. - Fixed blocks in hand facing wrong direction. ## [1.0.2] - 2016-09-14 ### Changed - \+64 in crafting start GUI now gives 64 from the first time instead of 65. ### Fixed - Fixed processing patterns not handling item insertion sometimes. ### Removed - Removed crafting task limit in crafting start GUI. ## [1.0.1] - 2016-09-13 ### Added - 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. - Added an option for the Crafter to trigger autocrafting with a redstone signal. ### Changed - Updated to Forge 2084. ### Fixed - Fixed advanced tooltips showing in Grid when not configured to do so. - Optimized crafting pattern loading. ## [1.0.0] - 2016-09-12 ### Added - Interface now supports Crafting Upgrade. - Implemented multithreaded autocrafting. ### Changed - Processing patterns now hold their items back for pushing until all the required items are gathered from the system. - Reworked Crafting Monitor GUI. - When shift clicking a recipe in the Crafting Grid, the player inventory is now leveraged as well. - Updated to Forge 2077. - Due to the new crafting system, all Crafting Patterns made before 1.0 have to be re-made. ### Fixed - Fixed item and fluid storage stored count having incorrect values at times. - Fixed problems relating to Crafting Upgrade (scheduling a task wrongly, blocking other tasks, etc). - Fixed machines breaking on long distances. - Fixed Controller rebuilding network graph on energy change. - Fixed fluids not caring about NBT tags. - Fixed fluids that have less than 1 bucket stored render only partly in Fluid Grid. - Fixed Fluid Interface voiding bucket when shift clicking to out slot. - Fixed wrong machine connection logic. ## [0.9.4-beta] - 2016-08-27 ### Changed - Reduced explosion radius when multiple controllers are connected to the same network. ### Fixed - Fixed mod not working without JEI. - Little fixes in German translation. - Reverted network changes that caused buggy behavior. ## [0.9.3-beta] - 2016-08-26 ### Added - Added Chinese translation. - Added Crafting Tweaks integration. ### Changed - Updated German translation for Fluid Storage. - Updated Dutch translation for Fluid Storage. - Reworked storage network code, should fix weird machine disconnection issues. ### Fixed - Fixed that the Fluid Storage Disk recipe returns an invalid disk. ## [0.9.2-beta] - 2016-08-25 ### Fixed - Fixed not being able to take out items from Wireless Grid cross-dimensionally. ## [0.9.1-beta] - 2016-08-24 ### Fixed - Fixed server crash with Grid. ## [0.9.0-beta] - 2016-08-24 ### Added - Added fluid storage. - Added Russian translation. ### Changed - Energy usage of Wireless Grid is now configurable. - Wireless Transmitters can now only be placed on Cable. - Priority field and detector amount field can now display 4 digits at a time. ### Fixed - Fixed crash with Grid. - Fixed Grid Filter only updating the Grid when reopening the GUI. - Fixed Wireless Grid not working cross dimensionally. - Fixed Grid not displaying items after changing redstone mode. - Fixed Wireless Transmitter crashing when it is transmitting to a removed dimension. - Fixed disassembling stacked Storage Blocks only returns 1 set of items. ## [0.8.20-beta] - 2016-08-18 ### Fixed - Fixed crash with Grid. ## [0.8.19-beta] - 2016-08-13 ### Fixed - Fixed item duplication bug with External Storage. - Fixed External Storage taking too long to update storage. - Fixed crash with Grid. - Fixed crash when shift clicking unsupported item in a slot. ## [0.8.18-beta] - 2016-08-11 ### Fixed - Fixed Detector mode not persisting. - Fixed bug where scrollbar didn't scroll correctly and thus hiding some items. - Fixed Network Transmitter not dropping inventory when broken. ## [0.8.17-beta] - 2016-08-09 ### Fixed - Fixed Grid causing sorting lag on the client. ## [0.8.16-beta] - 2016-08-09 ### Added - Added German translation by ChillUpX. - Added MCMultiPart integration for Cable Parts. ### Changed - You now have to click the actual cable part head in order to get the GUI open. - Grid Filters can now only filter 9 items, but, Grids take 4 filters now instead. - Grid Filters can now be configured to compare on NBT and/ or damage. - It is now possible to shift click items to the Storage Device filters. - Updated to Forge 2046. - Updated Tesla. - Java 8 is now a requirement. - Slight performance increase and network efficiency improvement in all GUI's. - Slight performance increase in Grid GUI. - Improved collisions of Cable parts. ### Fixed - Fixed issue with IC2 integration causing console spam. - Fixed not being able to change some configs in blocks. - Fixed serverside configs not syncing up with clientside. - Fixed not being able to move inventory items in Grid GUI's to hotbar via the number keys. - Fixed Relays when being in "Ignore Redstone" mode using up energy. - Fixed Crafter facing bottom side on placement. ## [0.8.15-beta] - 2016-08-01 ### Fixed - Fixed server startup crash. ## [0.8.14-beta] - 2016-08-01 ### Added - Added Interdimensional Upgrade so the Network Transmitter can work over different dimensions. ## [0.8.13-beta] - 2016-07-31 ### Added - Added config option to set the base energy usage of the Controller (default is 0). - Added Grid Filter item to filter items in any Grid. - Added support for processing patterns with big stacksizes. - Added Network Transmitter, Network Receiver and Network Cards. ### Changed - 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. - Changed Relay recipe to use redstone torch instead of Basic Processor. - Placed machines now face the block they are placed on, like hoppers. ### Fixed - Fixed rendering crash with Disk Drive. - Fixed crash when quickly toggling sorting direction in Grid. - Fixed not being able to clear exporter row in interface. ## [0.8.12-beta] - 2016-07-20 ### Fixed - Fixed dupe bug when shift clicking output slot in grid. ## [0.8.11-beta] - 2016-07-19 ### Added - Added X button to Processing Pattern Encoder to clear configuration of inputs and outputs. - Added Grid view toggle buttons (regular, craftable items only, no craftable items). - Added ability to shift click items into Importer, Exporter, Constructor, Destructor and Detector to set up whitelist / blacklist configurations easier. - Re-added opposite facing on shift click functionality. ### Changed - Solderer upgrades go to upgrades slots first now when shift clicking. - Updated to Forge 2014. ### Fixed - Fixed minor dupe bug with JEI transferring. - Fixed exporter crafting upgrades taking priority over other tasks. - Fixed NPE with incorrectly initialized disks. - Fixed not being able to take out items of Grid 2K16. - Fixed not being able to start autocrafting for certain items (most notably IC2 items). ## [0.8.10-beta] - 2016-07-13 ### Fixed - Fixed not being able to get some items out of Grid. - Fixed slight glitch in Constructor and Destructor model. ## [0.8.9-beta] - 2016-07-10 ### Added - Added a model for the Constructor. - Added a model for the Destructor. ### Changed - 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. - Some models / texture tweaks. ### Fixed - Fixed bug where Grid crafting doesn't handle remainder sometimes. - Fixed caching issues with External Storage. - Fixed possible crash with Disk Drives. ## [0.8.8-beta] - 2016-07-10 ### Changed - Use ore dictionary for recipes with glass. - Texture tweaks. ### Fixed - Fixed solderer not working with automation anymore. ## [0.8.7-beta] - 2016-07-09 ### Added - Added better hitbox for the Solderer. ### Changed - Wireless Transmitter is now only bright red when connected. - Improved detector model, add a better hitbox for it. - Improved the Wireless Transmitter texture. - Made the Solderer beams be bright red when they are working. ### Fixed - Fixed crash with External Storage. - Fixed Detector not unpowering when disconnected from the network. ## [0.8.6-beta] - 2016-07-09 ### Added - Re-added Controllers exploding when two of them are connected to the same network. - Added new textures. - Added model for External Storage. - Added model for Importer. - Added model for Exporter. - Added model for Detector. ### Changed - Huge performance improvements to large storage networks. - Limited some blocks to only have a direction on the x-axis. - Decreased amount of block updates significantly. ### Fixed - Fixed External Storage disconnecting on world reload. - Fixed External Storage not updating correctly. - Fixed wireless signal starting from Controller instead of per Wireless Transmitter individually. - Fixed Controller's redstone state not saving. - Fixed crafting tasks not saving properly. ### Removed - Removed opposite facing on placement mechanic. - Removed Quartz Enriched Iron Block. ## [0.8.5-beta] - 2016-07-04 ### Fixed - Fixed crash when Tesla API is not installed. ## [0.8.4-beta] - 2016-07-04 ### Added - Added a debug storage disk. - Added tooltip to solderer progress bar that shows progress percentage. - Added support for the Tesla energy system. - Added support for the IC2 (EU) energy system. - Added a Portuguese (Brazilian) translation. ### Changed - Performance improvements. - Tweaked grid GUI. ### Removed - Removed delay until grid items are visible. ## [0.8.3-beta] - 2016-07-02 ### Fixed - Fixed drawer controllers not working with external storage. - Fixed right click taking 64 items instead of 32 items. ## [0.8.2-beta] - 2016-07-01 ### Changed - It is now possible to use middle click multiple times for the same item in grid. - Made the mod configurable with a config file. ### Fixed - Fixed not being able to take items sometimes. ## [0.8.1-beta] - 2016-06-30 ### Fixed - Fixed upgrades from interface not dropping. - Fixed lag caused by constantly rebuilding storage. ## [0.8.0-beta] - 2016-06-25 ### Changed - Recompile for Minecraft 1.10. ### Fixed - Fixed solderer not using extra RF/t with upgrades. ## [0.7.19-beta] - 2016-06-25 ### Fixed - Fixed controller being buggy with reconnecting. - Fixed controller texture updating too slow when energy changes. - Fixed not being able to take item from grid at times. - Fixed external storage on storage drawer sending an item count of 0 over. ## [0.7.18-beta] - 2016-06-24 ### Fixed - Fixed cables sending updates when not needed. - Fixed cables not connecting to foreign machines that implement the API. ## [0.7.17-beta] - 2016-06-24 ### Changed - Updated Forge to 1969. - Updated JEI to 3.6.x. - Introduced new crafting settings GUI. - Tweaked some textures. ### Fixed - Fixed getting wrong items back in grid. - Fixed wrong item getting crafted. - Fixed server lag with exporter and importer. ## [0.7.16-beta] - 2016-06-19 ### Added - Added support for Storage Drawers void upgrade. - Added support for Deep Storage Unit API again. ### Fixed - Fixed NPE in machine searching. - Fixed a bug with interface giving negative amounts of items. - Fixed crash when using scroll wheel. ## [0.7.15-beta] - 2016-06-18 ### Fixed - Fixed not being able to scroll with the scroll wheel using MouseTweaks. - Fixed grid search box mode only changing after reopening GUI. ## [0.7.14-beta] - 2016-06-17 ### Added - Added shift clicking support to every inventory (for upgrades etc). - Added grid filtering options: @ for searching on mod items, # for searching on tooltips. - Added a way to clear patterns (shift + right click in inventory). ### Changed - Updated Forge to build 1965. - Tweaked some recipes. - Tweaked energy usage in some machines. ### Fixed - Fixed item overflow bug with storage drawers and external storage. ## [0.7.13-beta] - 2016-06-16 ### Added - Added ability to triple click in grid. ## [0.7.12-beta] - 2016-06-14 ### Fixed - Fixed creative storage blocks and disks not working. - Fixed interface overflowing. ## [0.7.11-beta] - 2016-06-12 ### Changed - Right click on grid search bar clears the search query. ### Fixed - Fixed crash with wireless grid. - Fixed high RF/t usage on external storage. - Fixed that requesting crafting processing task yields too many tasks. ## [0.7.10-beta] - 2016-06-11 ### Fixed - Fixed inventories not saving correctly. - Fixed that the player can't shift-click patterns into the last 3 slots of the Crafter. ## [0.7.9-beta] - 2016-06-11 ### Added - Added an API. - Added Storage Drawers integration. - Added handling for patterns that return the same item. - Added stack splitting between multiple storages. - Added handling for patterns that give back the same item. ### Changed - Increased cable recipe to 12 cables. ### Fixed - Fixed not being able to place sugar cane. - Fixed not being able to place seeds. - Fixed stacks not splitting between storages correctly. - Fixed storage not saving ItemStack capabilities. - Fixed dropping items into crafting grid with mouse won't work if your mouse is in between items. - Fixed controller still drawing power even if disabled. ## [0.7.8-beta] - 2016-06-04 ### Changed - Updated to Forge 1951. ### Fixed - Fixed crash on some worlds. - Improved Grid performance when sorting on quantity. ## [0.7.7-beta] - 2016-06-04 ### Added - Added the Stack Upgrade. - Added Quartz Enriched Iron Block. - Added French translation by Leventovitch. ### Changed - New items now go to the first available storage that has items in it already. - Tweaked some recipes. ### Fixed - Fixed buggy reequip animation on wireless grid. - Fixed solderer not supporting ore dictionary. - Fixed recipes not supporting ore dictionary. - Fixed destructor not being able to destroy some blocks. - Fixed not being able to place or destroy sugar cane. - Fixed storage blocks not being dismantable. - Fixed getting more items than needed sometimes. - Performance improvements. ## [0.7.6-beta] - 2016-05-29 ### Changed - Updated to Forge 1932. ### Fixed - Fixed not being able to start an autocraft. ## [0.7.5-beta] - 2016-05-29 ### Fixed - Fixed wrong ascending / descending order in Grid. - Fixed autocrafting not giving back byproducts. - Fixed Solderer causing too many chunk updates. - Fixed Solderer slot sides being weird. - Performance improvements. ## [0.7.4-beta] - 2016-05-27 ### Changed - Updated to Forge 1922. ### Fixed - Performance improvements. ## [0.7.3-beta] - 2016-05-25 ### Changed - Crafting tasks are now sorted from new to old in the Crafting Monitor. - Broke Interface block inventory compatibility: make sure to take all your items out of your Interface blocks before you apply the update. ### Fixed - Fixed grid performance by not sending grid data so often. - Fixed silicon + quartz enriched iron not having oredict names. ## [0.7.2-beta] - 2016-05-24 ### Fixed - Fixed Importer getting stuck on slot. ## [0.7.1-beta] - 2016-05-24 ### Fixed - Fixed NPE in some tiles. - Fixed going out of crafting GUI not restoring state (scrollbar and search term). - Fixed not being able to create a pattern in disconnected Pattern Grid. - Fixed not being able to place cake or string. - Performance improvement to Grids. ## [0.7.0-beta] - 2016-05-23 ### Added - Port to Minecraft 1.9.4. ### Fixed - Fixed Crafting Grid / Pattern Grid not throwing items on break. ## [0.6.15-alpha] - 2016-05-29 ### Fixed - Fixed Solderer sides being weird. - Fixed Solderer causing too many block updates. ## [0.6.14-alpha] - 2016-05-28 ### Fixed - Fixed wrong ascending / descending order in Grid. - Performance improvements. ## [0.6.13-alpha] - 2016-05-27 ### Fixed - Performance improvements. ## [0.6.12-alpha] - 2016-05-25 ### Changed - Crafting tasks are now sorted from new to old in the Crafting Monitor. ### Fixed - Fixed Crafting Grid / Pattern Grid not throwing items on break. - Fixed NPE in some tiles. - Fixed going out of crafting GUI not restoring state (scrollbar and search term). - Fixed not being able to place cake or string. - Fixed Importer getting stuck on slot. - Fixed silicon + quartz enriched iron not having oredict names. - Performance improvement to Grids. ## [0.6.11-alpha] - 2016-05-23 ### Changed - Converted all inventories in the mod to Forge's item handler capability system. ### Fixed - Fixed crafting patterns crashing when item of an input or output no longer exists. - Fixed Grid letting the current held item flicker. - Fixed Importer / Exporter / External Storage not being able to push or pull out of the other side of a double chest. ## [0.6.10-alpha] - 2016-05-21 ### Changed - Increased max crafting request size to 500. ### Fixed - Fixed Processing Patterns not working. - Fixed not being able to request more than 1 item at once. - Fixed crash with the Solderer. ## [0.6.9-alpha] - 2016-05-20 ### Added - Added automation for the Solderer: every side corresponds to a slot (see the wiki). ### Fixed - Fixed bug where machines wouldn't disconnect / connect when needed outside of chunk. - Fixed not being able to toggle redstone mode in a Wireless Transmitter. - Fixed same machine being connected to the network multiple times. - Fixed External Storage not working. - Reduced network usage. ## [0.6.8-alpha] - 2016-05-19 ### Fixed - Fixed CTRL + pick block on machines crashing game. - Performance improvements. ## [0.6.7-alpha] - 2016-05-19 ### Fixed - Performance improvements. ## [0.6.6-alpha] - 2016-05-18 ### Fixed - Fixed being able to insert non-allowed items in inventories with hoppers. - Fixed Processing Pattern Encoder not using up a Pattern. ## [0.6.5-alpha] - 2016-05-18 ### Changed - Updated Forge to build 1907. ### Fixed - Performance improvements for servers. - Performance improvements for client scrollbars. ## [0.6.4-alpha] - 2016-05-17 ### Fixed - Performance improvements. ## [0.6.3-alpha] - 2016-05-17 ### Fixed - Performance improvements. ## [0.6.2-alpha] - 2016-05-17 ### Added - Added a max crafting quantity per request cap (hardcoded to 100). ### Changed - Upgrades now draw extra energy. ### Fixed - Fixed race condition with crafting tasks. - Fixed pressing escape in crafting settings GUI not going back to grid GUI. - Fixed losing autoselection in Grid when clicking on slot with autoselection mode. - Fixed being able to pick up from pattern result slot. ## [0.6.1-alpha] - 2016-05-16 ### Fixed - Fixed NPE on world load. - Fixed Destructor crashing when removing a connected machine. ## [0.6.0-alpha] - 2016-05-16 ### Added - Added autocrafting. - Added the Pattern Grid. - Added the Crafting Monitor. - Added the Crafter. - Added the Processing Pattern Encoder. - Added a Pattern item. - Added the Wireless Transmitter. - Added Speed Upgrades which are applicable on a bunch of machines. - Added Range Upgrades for in the Wireless Transmitter. - Added Crafting Upgrades. - Added recipe category -> item JEI integration. - Added Storage Housing. ### Changed - Changed Grid modes to have a autoselected option. ### Fixed - Fixed Destructor not playing block break sound. - Fixed Constructor not playing block place sound. - Fixed picking up from crafting result slot. - Fixed being able to use right click on crafting result slot. - Fixed item duplication issue with the Interface. - Fixed Importers and Exporters not working when changing facing with a wrench. - Fixed Crafting Grid not respecting remainder in recipes. - Fixed Crafting Grid giving back the wrong amount of items when shift clicking. - Fixed items disappearing in Grid when doing a weird combination of inputs. - Fixed Solderer not stacking items. - Fixed Importer voiding Storage Disks from the Disk Drive. - Fixed Controller not saving energy. - Massive performance improvements which reduces lag and lets machines connect almost instantly. ## [0.5.6-alpha] - 2016-04-29 ### Fixed - Fixed sorting crash. - Fixed autofocusing on priority field in storage GUIs. - Fixed controller causing lag when energy level changes. ## [0.5.5-alpha] - 2016-04-09 ### Changed - Updated to Forge 1859. ### Fixed - Fixed several crashes. - Energy level on Controller is maintained. ## [0.5.4-alpha] - 2016-04-05 ### Changed - Shift clicking on placing Constructor and Destructor will have opposite direction. ### Fixed - Fixed machines out of the Controller's chunk range only connecting after block break when rejoining the world. - Fixed scrollbar skipping some rows when scrolling with mouse wheel. - Fixed machines from a long distance not being visible in the Controller. ## [0.5.3-alpha] - 2016-04-04 ### Added - Added a Creative Wireless Grid. ### Changed - Changed block hardness levels. ### Fixed - Fixed not being able to open a Grid that is 256 blocks away from the Controller. - Made the mod way less network intensive. ## [0.5.2-alpha] - 2016-04-03 ### Added - Items that don't exist anymore, won't be added to storage again to avoid crashes. ### Fixed - Fixed not being able to run the mod without JEI. ## [0.5.1-alpha] - 2016-04-03 ### Fixed - Fixed Disk Drive crashing with an `AbstractMethodException`. ## [0.5.0-alpha] - 2016-04-03 ### Added - Deep Storage Unit integration (with this several barrel mods are now supported too!). - 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). - Added mass crafting of items with shift in Crafting Grid. - Added JEI recipe transfering in Crafting Grid. - New textures. - Scrollbar in Grid and Crafting Grid. - Display of connected machines in the Controller GUI. - Nice formatting for items >= 1K (pressing shift while hovering over an item will still display the real item count). - Grid can now synchronize with JEI. ### Changed - Updated to the latest Forge and JEI. - Renamed Drives to Disk Drives. - Renamed Storage Cells to Storage Disks. - Wireless Grid is now bound to a Controller instead of a Grid. - Drives have a better interface and there are now blacklist and whitelist filters for the Storage Disks in it too. - Destructors have the ability to whitelist and blacklist certain items now. - Side buttons in machine GUIs are now left, not right. - Shift clicking stuff in the Interface. - Made the normal Grid 1 row larger. - Machines don't need to be connected with cables anymore, they can be next to each other too. - Made the amount text in the Grid for items smaller. ### Fixed - Fixed clicking sound in Grid. - Fixed a bunch of crashes. - Fixed Exporter not exporting is some cases. - Fixed Importer not importing in some cases. - Fixed Controller drawing RF every 20 ticks instead of every tick. - Fixed not being able to shift click from Crafting Grid crafting slots. - Fixed new items inserted after crafting in Grid being laggy. - Fixed flickering of items in Grid. - Fixed getting a stack of unstackable items from Grid. - Fixed Cable not having a collision box. - Check if the Constructor can actually place said block in the world. ### Removed - Removed Wireless Transmitters. ## [0.4.1-alpha] - 2016-03-24 ### Fixed - Fixed ID duplication issues. ## [0.4.0-alpha] - 2016-03-21 ### Added - Relays. - Interfaces. ### Changed - Cables now have actual collision. ### Fixed - Fix Minecraft reporting that retrieving Grid type fails. - Fullness percentage in Creative Storage Blocks going under 0%. - The Controller shouldn't display the base usage when not working. - Check if item is valid for slot before pushing to inventories. ## [0.3.0-alpha] - 2016-03-20 ### Added - Initial release for Minecraft 1.9. ## [0.2.1-alpha] - 2016-02-03 ### Added - Internal test release. ## [0.2.0-alpha] - 2016-01-31 ### Added - Internal test release. ## [0.1.1-alpha] - 2016-01-31 ### Added - Internal test release. ## [0.1.0-alpha] - 2016-01-03 ### Added - Internal test release. [Unreleased]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.4...HEAD [1.13.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.3...v1.13.0-beta.4 [1.13.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.2...v1.13.0-beta.3 [1.13.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.13.0-beta.1...v1.13.0-beta.2 [1.13.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.12.4...v1.13.0-beta.1 [1.12.4]: https://github.com/refinedmods/refinedstorage/compare/v1.12.3...v1.12.4 [1.12.3]: https://github.com/refinedmods/refinedstorage/compare/v1.12.2...v1.12.3 [1.12.2]: https://github.com/refinedmods/refinedstorage/compare/v1.12.1...v1.12.2 [1.12.1]: https://github.com/refinedmods/refinedstorage/compare/v1.12.0...v1.12.1 [1.12.0]: https://github.com/refinedmods/refinedstorage/compare/v1.11.7...v1.12.0 [1.11.7]: https://github.com/refinedmods/refinedstorage/compare/v1.11.6...v1.11.7 [1.11.6]: https://github.com/refinedmods/refinedstorage/compare/v1.11.5...v1.11.6 [1.11.5]: https://github.com/refinedmods/refinedstorage/compare/v1.11.4...v1.11.5 [1.11.4]: https://github.com/refinedmods/refinedstorage/compare/v1.11.3...v1.11.4 [1.11.3]: https://github.com/refinedmods/refinedstorage/compare/v1.11.2...v1.11.3 [1.11.2]: https://github.com/refinedmods/refinedstorage/compare/v1.11.1...v1.11.2 [1.11.1]: https://github.com/refinedmods/refinedstorage/compare/v1.11.0...v1.11.1 [1.11.0]: https://github.com/refinedmods/refinedstorage/compare/v1.10.6...v1.11.0 [1.10.6]: https://github.com/refinedmods/refinedstorage/compare/v1.10.5...v1.10.6 [1.10.5]: https://github.com/refinedmods/refinedstorage/compare/v1.10.4...v1.10.5 [1.10.4]: https://github.com/refinedmods/refinedstorage/compare/v1.10.3...v1.10.4 [1.10.3]: https://github.com/refinedmods/refinedstorage/compare/v1.10.2...v1.10.3 [1.10.2]: https://github.com/refinedmods/refinedstorage/compare/v1.10.1...v1.10.2 [1.10.1]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0...v1.10.1 [1.10.0]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.4...v1.10.0 [1.10.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.3...v1.10.0-beta.4 [1.10.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.2...v1.10.0-beta.3 [1.10.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.10.0-beta.1...v1.10.0-beta.2 [1.10.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.9.18...v1.10.0-beta.1 [1.9.18]: https://github.com/refinedmods/refinedstorage/compare/v1.9.17...v1.9.18 [1.9.17]: https://github.com/refinedmods/refinedstorage/compare/v1.9.16...v1.9.17 [1.9.16]: https://github.com/refinedmods/refinedstorage/compare/v1.9.15...v1.9.16 [1.9.15]: https://github.com/refinedmods/refinedstorage/compare/v1.9.14...v1.9.15 [1.9.14]: https://github.com/refinedmods/refinedstorage/compare/v1.9.13...v1.9.14 [1.9.13]: https://github.com/refinedmods/refinedstorage/compare/v1.9.12...v1.9.13 [1.9.12]: https://github.com/refinedmods/refinedstorage/compare/v1.9.11...v1.9.12 [1.9.11]: https://github.com/refinedmods/refinedstorage/compare/v1.9.10...v1.9.11 [1.9.10]: https://github.com/refinedmods/refinedstorage/compare/v1.9.9...v1.9.10 [1.9.9]: https://github.com/refinedmods/refinedstorage/compare/v1.9.8...v1.9.9 [1.9.8]: https://github.com/refinedmods/refinedstorage/compare/v1.9.7...v1.9.8 [1.9.7]: https://github.com/refinedmods/refinedstorage/compare/v1.9.6...v1.9.7 [1.9.6]: https://github.com/refinedmods/refinedstorage/compare/v1.9.5...v1.9.6 [1.9.5]: https://github.com/refinedmods/refinedstorage/compare/v1.9.4...v1.9.5 [1.9.4]: https://github.com/refinedmods/refinedstorage/compare/v1.9.3-beta...v1.9.4 [1.9.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.9.2-beta.2...v1.9.3-beta [1.9.2-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.9.2-beta.1...v1.9.2-beta.2 [1.9.2-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.9.1-beta...v1.9.2-beta.1 [1.9.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.9.0-beta...v1.9.1-beta [1.9.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.8...v1.9.0-beta [1.8.8]: https://github.com/refinedmods/refinedstorage/compare/v1.8.7...v1.8.8 [1.8.7]: https://github.com/refinedmods/refinedstorage/compare/v1.8.6-beta...v1.8.7 [1.8.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.5-beta...v1.8.6-beta [1.8.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.4-beta...v1.8.5-beta [1.8.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.3-beta...v1.8.4-beta [1.8.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.2-beta...v1.8.3-beta [1.8.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.1-beta...v1.8.2-beta [1.8.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.8.0-beta...v1.8.1-beta [1.8.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.3-beta...v1.8.0-beta [1.7.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.2-beta...v1.7.3-beta [1.7.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.7.1-alpha...v1.7.2-beta [1.7.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0-alpha...v1.7.1-alpha [1.7.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+10...v1.7.0-alpha [1.7.0+10]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+9...v1.7.0+10 [1.7.0+9]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+8...v1.7.0+9 [1.7.0+8]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+7...v1.7.0+8 [1.7.0+7]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+6...v1.7.0+7 [1.7.0+6]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+5...v1.7.0+6 [1.7.0+5]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+4...v1.7.0+5 [1.7.0+4]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+3...v1.7.0+4 [1.7.0+3]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+2...v1.7.0+3 [1.7.0+2]: https://github.com/refinedmods/refinedstorage/compare/v1.7.0+1...v1.7.0+2 [1.7.0+1]: https://github.com/refinedmods/refinedstorage/compare/v1.6.16...v1.7.0+1 [1.6.16]: https://github.com/refinedmods/refinedstorage/compare/v1.6.15...v1.6.16 [1.6.15]: https://github.com/refinedmods/refinedstorage/compare/v1.6.14...v1.6.15 [1.6.14]: https://github.com/refinedmods/refinedstorage/compare/v1.6.13...v1.6.14 [1.6.13]: https://github.com/refinedmods/refinedstorage/compare/v1.6.12...v1.6.13 [1.6.12]: https://github.com/refinedmods/refinedstorage/compare/v1.6.11...v1.6.12 [1.6.11]: https://github.com/refinedmods/refinedstorage/compare/v1.6.10...v1.6.11 [1.6.10]: https://github.com/refinedmods/refinedstorage/compare/v1.6.9...v1.6.10 [1.6.9]: https://github.com/refinedmods/refinedstorage/compare/v1.6.8...v1.6.9 [1.6.8]: https://github.com/refinedmods/refinedstorage/compare/v1.6.7...v1.6.8 [1.6.7]: https://github.com/refinedmods/refinedstorage/compare/v1.6.6...v1.6.7 [1.6.6]: https://github.com/refinedmods/refinedstorage/compare/v1.6.5...v1.6.6 [1.6.5]: https://github.com/refinedmods/refinedstorage/compare/v1.6.4...v1.6.5 [1.6.4]: https://github.com/refinedmods/refinedstorage/compare/v1.6.3...v1.6.4 [1.6.3]: https://github.com/refinedmods/refinedstorage/compare/v1.6.2...v1.6.3 [1.6.2]: https://github.com/refinedmods/refinedstorage/compare/v1.6.1...v1.6.2 [1.6.1]: https://github.com/refinedmods/refinedstorage/compare/v1.6.0...v1.6.1 [1.6.0]: https://github.com/refinedmods/refinedstorage/compare/v1.5.34...v1.6.0 [1.5.34]: https://github.com/refinedmods/refinedstorage/compare/v1.5.33...v1.5.34 [1.5.33]: https://github.com/refinedmods/refinedstorage/compare/v1.5.32...v1.5.33 [1.5.32]: https://github.com/refinedmods/refinedstorage/compare/v1.5.31...v1.5.32 [1.5.31]: https://github.com/refinedmods/refinedstorage/compare/v1.5.30...v1.5.31 [1.5.30]: https://github.com/refinedmods/refinedstorage/compare/v1.5.29...v1.5.30 [1.5.29]: https://github.com/refinedmods/refinedstorage/compare/v1.5.28...v1.5.29 [1.5.28]: https://github.com/refinedmods/refinedstorage/compare/v1.5.27-beta...v1.5.28 [1.5.27-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.26-beta...v1.5.27-beta [1.5.26-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.25...v1.5.26-beta [1.5.25]: https://github.com/refinedmods/refinedstorage/compare/v1.5.24...v1.5.25 [1.5.24]: https://github.com/refinedmods/refinedstorage/compare/v1.5.23...v1.5.24 [1.5.23]: https://github.com/refinedmods/refinedstorage/compare/v1.5.22...v1.5.23 [1.5.22]: https://github.com/refinedmods/refinedstorage/compare/v1.5.21...v1.5.22 [1.5.21]: https://github.com/refinedmods/refinedstorage/compare/v1.5.20...v1.5.21 [1.5.20]: https://github.com/refinedmods/refinedstorage/compare/v1.5.19...v1.5.20 [1.5.19]: https://github.com/refinedmods/refinedstorage/compare/v1.5.18...v1.5.19 [1.5.18]: https://github.com/refinedmods/refinedstorage/compare/v1.5.17...v1.5.18 [1.5.17]: https://github.com/refinedmods/refinedstorage/compare/v1.5.16...v1.5.17 [1.5.16]: https://github.com/refinedmods/refinedstorage/compare/v1.5.15...v1.5.16 [1.5.15]: https://github.com/refinedmods/refinedstorage/compare/v1.5.14...v1.5.15 [1.5.14]: https://github.com/refinedmods/refinedstorage/compare/v1.5.13...v1.5.14 [1.5.13]: https://github.com/refinedmods/refinedstorage/compare/v1.5.12...v1.5.13 [1.5.12]: https://github.com/refinedmods/refinedstorage/compare/v1.5.11...v1.5.12 [1.5.11]: https://github.com/refinedmods/refinedstorage/compare/v1.5.10...v1.5.11 [1.5.10]: https://github.com/refinedmods/refinedstorage/compare/v1.5.9...v1.5.10 [1.5.9]: https://github.com/refinedmods/refinedstorage/compare/v1.5.8...v1.5.9 [1.5.8]: https://github.com/refinedmods/refinedstorage/compare/v1.5.7...v1.5.8 [1.5.7]: https://github.com/refinedmods/refinedstorage/compare/v1.5.6...v1.5.7 [1.5.6]: https://github.com/refinedmods/refinedstorage/compare/v1.5.5-beta...v1.5.6 [1.5.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.4-beta...v1.5.5-beta [1.5.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.3-beta...v1.5.4-beta [1.5.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.2-beta...v1.5.3-beta [1.5.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.1-beta...v1.5.2-beta [1.5.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.5.0-alpha...v1.5.1-beta [1.5.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.4.20...v1.5.0-alpha [1.4.20]: https://github.com/refinedmods/refinedstorage/compare/v1.4.19...v1.4.20 [1.4.19]: https://github.com/refinedmods/refinedstorage/compare/v1.4.18...v1.4.19 [1.4.18]: https://github.com/refinedmods/refinedstorage/compare/v1.4.17...v1.4.18 [1.4.17]: https://github.com/refinedmods/refinedstorage/compare/v1.4.16...v1.4.17 [1.4.16]: https://github.com/refinedmods/refinedstorage/compare/v1.4.15...v1.4.16 [1.4.15]: https://github.com/refinedmods/refinedstorage/compare/v1.4.14...v1.4.15 [1.4.14]: https://github.com/refinedmods/refinedstorage/compare/v1.4.13...v1.4.14 [1.4.13]: https://github.com/refinedmods/refinedstorage/compare/v1.4.12...v1.4.13 [1.4.12]: https://github.com/refinedmods/refinedstorage/compare/v1.4.11...v1.4.12 [1.4.11]: https://github.com/refinedmods/refinedstorage/compare/v1.4.10-beta...v1.4.11 [1.4.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.9-beta...v1.4.10-beta [1.4.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.8-beta...v1.4.9-beta [1.4.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.7-beta...v1.4.8-beta [1.4.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.6-beta...v1.4.7-beta [1.4.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.5-beta...v1.4.6-beta [1.4.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.4-beta...v1.4.5-beta [1.4.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.3-beta...v1.4.4-beta [1.4.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.2-beta...v1.4.3-beta [1.4.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.1-beta...v1.4.2-beta [1.4.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.4.0-beta...v1.4.1-beta [1.4.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v1.3.5-alpha...v1.4.0-beta [1.3.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.4-alpha...v1.3.5-alpha [1.3.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.3-alpha...v1.3.4-alpha [1.3.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.2-alpha...v1.3.3-alpha [1.3.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.1-alpha...v1.3.2-alpha [1.3.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.3.0-alpha...v1.3.1-alpha [1.3.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v1.2.26...v1.3.0-alpha [1.2.26]: https://github.com/refinedmods/refinedstorage/compare/v1.2.25...v1.2.26 [1.2.25]: https://github.com/refinedmods/refinedstorage/compare/v1.2.24...v1.2.25 [1.2.24]: https://github.com/refinedmods/refinedstorage/compare/v1.2.23...v1.2.24 [1.2.23]: https://github.com/refinedmods/refinedstorage/compare/v1.2.22...v1.2.23 [1.2.22]: https://github.com/refinedmods/refinedstorage/compare/v1.2.21...v1.2.22 [1.2.21]: https://github.com/refinedmods/refinedstorage/compare/v1.2.20...v1.2.21 [1.2.20]: https://github.com/refinedmods/refinedstorage/compare/v1.2.19...v1.2.20 [1.2.19]: https://github.com/refinedmods/refinedstorage/compare/v1.2.18...v1.2.19 [1.2.18]: https://github.com/refinedmods/refinedstorage/compare/v1.2.17...v1.2.18 [1.2.17]: https://github.com/refinedmods/refinedstorage/compare/v1.2.16...v1.2.17 [1.2.16]: https://github.com/refinedmods/refinedstorage/compare/v1.2.15...v1.2.16 [1.2.15]: https://github.com/refinedmods/refinedstorage/compare/v1.2.14...v1.2.15 [1.2.14]: https://github.com/refinedmods/refinedstorage/compare/v1.2.13...v1.2.14 [1.2.13]: https://github.com/refinedmods/refinedstorage/compare/v1.2.12...v1.2.13 [1.2.12]: https://github.com/refinedmods/refinedstorage/compare/v1.2.11...v1.2.12 [1.2.11]: https://github.com/refinedmods/refinedstorage/compare/v1.2.10...v1.2.11 [1.2.10]: https://github.com/refinedmods/refinedstorage/compare/v1.2.9...v1.2.10 [1.2.9]: https://github.com/refinedmods/refinedstorage/compare/v1.2.8...v1.2.9 [1.2.8]: https://github.com/refinedmods/refinedstorage/compare/v1.2.7...v1.2.8 [1.2.7]: https://github.com/refinedmods/refinedstorage/compare/v1.2.6...v1.2.7 [1.2.6]: https://github.com/refinedmods/refinedstorage/compare/v1.2.5...v1.2.6 [1.2.5]: https://github.com/refinedmods/refinedstorage/compare/v1.2.4...v1.2.5 [1.2.4]: https://github.com/refinedmods/refinedstorage/compare/v1.2.3...v1.2.4 [1.2.3]: https://github.com/refinedmods/refinedstorage/compare/v1.2.2...v1.2.3 [1.2.2]: https://github.com/refinedmods/refinedstorage/compare/v1.2.1...v1.2.2 [1.2.1]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0...v1.2.1 [1.2.0]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.8...v1.2.0 [1.2.0-beta.8]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.7...v1.2.0-beta.8 [1.2.0-beta.7]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.6...v1.2.0-beta.7 [1.2.0-beta.6]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.5...v1.2.0-beta.6 [1.2.0-beta.5]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.4...v1.2.0-beta.5 [1.2.0-beta.4]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.3...v1.2.0-beta.4 [1.2.0-beta.3]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.2...v1.2.0-beta.3 [1.2.0-beta.2]: https://github.com/refinedmods/refinedstorage/compare/v1.2.0-beta.1...v1.2.0-beta.2 [1.2.0-beta.1]: https://github.com/refinedmods/refinedstorage/compare/v1.1.3...v1.2.0-beta.1 [1.1.3]: https://github.com/refinedmods/refinedstorage/compare/v1.1.2...v1.1.3 [1.1.2]: https://github.com/refinedmods/refinedstorage/compare/v1.1.1...v1.1.2 [1.1.1]: https://github.com/refinedmods/refinedstorage/compare/v1.1.0...v1.1.1 [1.1.0]: https://github.com/refinedmods/refinedstorage/compare/v1.0.5...v1.1.0 [1.0.5]: https://github.com/refinedmods/refinedstorage/compare/v1.0.4...v1.0.5 [1.0.4]: https://github.com/refinedmods/refinedstorage/compare/v1.0.3...v1.0.4 [1.0.3]: https://github.com/refinedmods/refinedstorage/compare/v1.0.2...v1.0.3 [1.0.2]: https://github.com/refinedmods/refinedstorage/compare/v1.0.1...v1.0.2 [1.0.1]: https://github.com/refinedmods/refinedstorage/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/refinedmods/refinedstorage/compare/v0.9.4-beta...v1.0.0 [0.9.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.3-beta...v0.9.4-beta [0.9.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.2-beta...v0.9.3-beta [0.9.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.1-beta...v0.9.2-beta [0.9.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.9.0-beta...v0.9.1-beta [0.9.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.20-beta...v0.9.0-beta [0.8.20-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.19-beta...v0.8.20-beta [0.8.19-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.18-beta...v0.8.19-beta [0.8.18-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.17-beta...v0.8.18-beta [0.8.17-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.16-beta...v0.8.17-beta [0.8.16-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.15-beta...v0.8.16-beta [0.8.15-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.14-beta...v0.8.15-beta [0.8.14-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.13-beta...v0.8.14-beta [0.8.13-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.12-beta...v0.8.13-beta [0.8.12-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.11-beta...v0.8.12-beta [0.8.11-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.10-beta...v0.8.11-beta [0.8.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.9-beta...v0.8.10-beta [0.8.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.8-beta...v0.8.9-beta [0.8.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.7-beta...v0.8.8-beta [0.8.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.6-beta...v0.8.7-beta [0.8.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.5-beta...v0.8.6-beta [0.8.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.4-beta...v0.8.5-beta [0.8.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.3-beta...v0.8.4-beta [0.8.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.2-beta...v0.8.3-beta [0.8.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.1-beta...v0.8.2-beta [0.8.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.8.0-beta...v0.8.1-beta [0.8.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.19-beta...v0.8.0-beta [0.7.19-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.18-beta...v0.7.19-beta [0.7.18-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.17-beta...v0.7.18-beta [0.7.17-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.16-beta...v0.7.17-beta [0.7.16-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.15-beta...v0.7.16-beta [0.7.15-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.14-beta...v0.7.15-beta [0.7.14-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.13-beta...v0.7.14-beta [0.7.13-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.12-beta...v0.7.13-beta [0.7.12-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.11-beta...v0.7.12-beta [0.7.11-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.10-beta...v0.7.11-beta [0.7.10-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.9-beta...v0.7.10-beta [0.7.9-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.8-beta...v0.7.9-beta [0.7.8-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.7-beta...v0.7.8-beta [0.7.7-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.6-beta...v0.7.7-beta [0.7.6-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.5-beta...v0.7.6-beta [0.7.5-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.4-beta...v0.7.5-beta [0.7.4-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.3-beta...v0.7.4-beta [0.7.3-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.2-beta...v0.7.3-beta [0.7.2-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.1-beta...v0.7.2-beta [0.7.1-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.7.0-beta...v0.7.1-beta [0.7.0-beta]: https://github.com/refinedmods/refinedstorage/compare/v0.6.15-alpha...v0.7.0-beta [0.6.15-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.14-alpha...v0.6.15-alpha [0.6.14-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.13-alpha...v0.6.14-alpha [0.6.13-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.12-alpha...v0.6.13-alpha [0.6.12-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.11-alpha...v0.6.12-alpha [0.6.11-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.10-alpha...v0.6.11-alpha [0.6.10-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.9-alpha...v0.6.10-alpha [0.6.9-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.8-alpha...v0.6.9-alpha [0.6.8-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.7-alpha...v0.6.8-alpha [0.6.7-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.6-alpha...v0.6.7-alpha [0.6.6-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.5-alpha...v0.6.6-alpha [0.6.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.4-alpha...v0.6.5-alpha [0.6.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.3-alpha...v0.6.4-alpha [0.6.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.2-alpha...v0.6.3-alpha [0.6.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.1-alpha...v0.6.2-alpha [0.6.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.6.0-alpha...v0.6.1-alpha [0.6.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.6-alpha...v0.6.0-alpha [0.5.6-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.5-alpha...v0.5.6-alpha [0.5.5-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.4-alpha...v0.5.5-alpha [0.5.4-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.3-alpha...v0.5.4-alpha [0.5.3-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.2-alpha...v0.5.3-alpha [0.5.2-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.1-alpha...v0.5.2-alpha [0.5.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.5.0-alpha...v0.5.1-alpha [0.5.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.4.1-alpha...v0.5.0-alpha [0.4.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.4.0-alpha...v0.4.1-alpha [0.4.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.3.0-alpha...v0.4.0-alpha [0.3.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.2.1-alpha...v0.3.0-alpha [0.2.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.2.0-alpha...v0.2.1-alpha [0.2.0-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.1.1-alpha...v0.2.0-alpha [0.1.1-alpha]: https://github.com/refinedmods/refinedstorage/compare/v0.1.0-alpha...v0.1.1-alpha [0.1.0-alpha]: https://github.com/refinedmods/refinedstorage/releases/tag/v0.1.0-alpha ================================================ FILE: LICENSE.md ================================================ # The MIT License (MIT) Copyright © 2015 - 2025 Refined Mods Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================

⚠️ IMPORTANT NOTICE ⚠️

This repository is for Refined Storage v1.x.

🚫 v1.x is no longer maintained, and we do not accept issues for it.

🛠 Please report all bugs, issues, and suggestions for Refined Storage v2.x in the
Refined Storage 2 issue tracker.

Refined Storage logo

Refined Storage

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.

[![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)
## About Items 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. This 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. ## Links - [GitHub](https://github.com/refinedmods/refinedstorage) - [Releases](https://github.com/refinedmods/refinedstorage/releases) - [Packages](https://github.com/refinedmods/refinedstorage/packages) - [Issues](https://github.com/refinedmods/refinedstorage/issues) - [Refined Mods on GitHub](https://github.com/refinedmods) - [CurseForge](https://curseforge.com/minecraft/mc-mods/refined-storage) - [Modrinth](https://modrinth.com/mod/refined-storage) - [Wiki](https://refinedmods.com/refined-storage/) - [Javadoc](https://refinedmods.com/javadoc/refinedstorage) - [Discord](https://discordapp.com/invite/VYzsydb) ## Building Clone the repository and import the Gradle project. ## Contributing See [CONTRIBUTING.md](.github/CONTRIBUTING.md). ## Support See [SUPPORT.md](.github/SUPPORT.md). ## Changelog See [CHANGELOG.md](CHANGELOG.md). ================================================ FILE: build.gradle ================================================ apply from: "https://raw.githubusercontent.com/refinedmods/refinedarchitect/v0.11.4/helper.gradle" repositories { maven { name = 'JEI' url = "https://maven.blamejared.com/" } maven { url "https://www.cursemaven.com" content { includeGroup "curse.maven" } } maven { name = 'Curios' url = "https://maven.theillusivec4.top/" } } group = 'com.refinedmods' forgeProject("refinedstorage") archivesBaseName = 'refinedstorage' enablePublishing() enableCurseForge(243076) enableModrinth("KDvYkUg3") enableJavadoc() dependencies { compileOnly "mezz.jei:jei-1.20.4-common-api:17.3.0.43" compileOnly "mezz.jei:jei-1.20.4-neoforge-api:17.3.0.43" runtimeOnly "mezz.jei:jei-1.20.4-neoforge:17.3.0.43" compileOnly "curse.maven:mouse-tweaks-60089:4776995" compileOnly 'curse.maven:crafting-tweaks-233071:4991559' implementation "top.theillusivec4.curios:curios-neoforge:7.2.0+1.20.4" } ================================================ FILE: config/checkstyle/checkstyle.xml ================================================ ================================================ FILE: docs/nav.json ================================================ [ { "title": "Home", "ref": "index.adoc", "icon": "bi-house-fill" }, { "title": "News", "ref": "news/index.adoc", "icon": "bi bi-newspaper" }, { "title": "Release notes", "ref": "release-notes.adoc", "icon": "bi bi-file-earmark-text" }, { "title": "Getting started", "ref": "getting-started.adoc", "icon": "bi-book" }, { "title": "FAQ", "ref": "faq.adoc", "icon": "bi-question-circle-fill" }, { "title": "Need help?", "ref": "need-help.adoc", "icon": "bi-person-raised-hand" }, { "title": "Networking", "ref": "networking/index.adoc", "children": [ { "ref": "networking/controller.adoc" }, { "ref": "networking/creative-controller.adoc" }, { "ref": "networking/cable.adoc" }, { "ref": "networking/detector.adoc" }, { "ref": "networking/relay.adoc" } ] }, { "title": "Storage", "ref": "storage/index.adoc", "children": [ { "ref": "storage/storing-externally.adoc" }, { "ref": "storage/storing-fluids.adoc" }, { "ref": "storage/disk-drive.adoc" }, { "ref": "storage/external-storage.adoc" }, { "ref": "storage/1k-storage-part.adoc" }, { "ref": "storage/4k-storage-part.adoc" }, { "ref": "storage/16k-storage-part.adoc" }, { "ref": "storage/64k-storage-part.adoc" }, { "ref": "storage/storage-housing.adoc" }, { "ref": "storage/1k-storage-disk.adoc" }, { "ref": "storage/4k-storage-disk.adoc" }, { "ref": "storage/16k-storage-disk.adoc" }, { "ref": "storage/64k-storage-disk.adoc" }, { "ref": "storage/creative-storage-disk.adoc" }, { "ref": "storage/1k-storage-block.adoc" }, { "ref": "storage/4k-storage-block.adoc" }, { "ref": "storage/16k-storage-block.adoc" }, { "ref": "storage/64k-storage-block.adoc" }, { "ref": "storage/creative-storage-block.adoc" }, { "ref": "storage/64k-fluid-storage-part.adoc" }, { "ref": "storage/256k-fluid-storage-part.adoc" }, { "ref": "storage/1024k-fluid-storage-part.adoc" }, { "ref": "storage/4096k-fluid-storage-part.adoc" }, { "ref": "storage/64k-fluid-storage-disk.adoc" }, { "ref": "storage/256k-fluid-storage-disk.adoc" }, { "ref": "storage/1024k-fluid-storage-disk.adoc" }, { "ref": "storage/4096k-fluid-storage-disk.adoc" }, { "ref": "storage/creative-fluid-storage-disk.adoc" }, { "ref": "storage/64k-fluid-storage-block.adoc" }, { "ref": "storage/256k-fluid-storage-block.adoc" }, { "ref": "storage/1024k-fluid-storage-block.adoc" }, { "ref": "storage/4096k-fluid-storage-block.adoc" }, { "ref": "storage/creative-fluid-storage-block.adoc" } ] }, { "title": "Viewing resources", "ref": "viewing-resources/index.adoc", "children": [ { "ref": "viewing-resources/how-to-view-resources.adoc" }, { "ref": "viewing-resources/grid.adoc" }, { "ref": "viewing-resources/crafting-grid.adoc" }, { "ref": "viewing-resources/fluid-grid.adoc" }, { "ref": "viewing-resources/storage-monitor.adoc" }, { "ref": "viewing-resources/portable-grid.adoc" } ] }, { "title": "Input and output", "ref": "input-and-output/index.adoc", "children": [ { "ref": "input-and-output/getting-items-in-and-out.adoc" }, { "ref": "input-and-output/importer.adoc" }, { "ref": "input-and-output/exporter.adoc" }, { "ref": "input-and-output/constructor.adoc" }, { "ref": "input-and-output/destructor.adoc" }, { "ref": "input-and-output/interface.adoc" }, { "ref": "input-and-output/fluid-interface.adoc" }, { "ref": "input-and-output/disk-manipulator.adoc" }, { "ref": "input-and-output/reader.adoc" }, { "ref": "input-and-output/writer.adoc" } ] }, { "title": "Wireless networking", "ref": "wireless-networking/index.adoc", "children": [ { "ref": "wireless-networking/networks-over-long-distances.adoc" }, { "ref": "wireless-networking/wireless-transmitter.adoc" }, { "ref": "wireless-networking/wireless-grid.adoc" }, { "ref": "wireless-networking/wireless-crafting-grid.adoc" }, { "ref": "wireless-networking/creative-wireless-grid.adoc" }, { "ref": "wireless-networking/wireless-fluid-grid.adoc" }, { "ref": "wireless-networking/creative-wireless-fluid-grid.adoc" }, { "ref": "wireless-networking/wireless-crafting-monitor.adoc" }, { "ref": "wireless-networking/creative-wireless-crafting-monitor.adoc" }, { "ref": "wireless-networking/network-card.adoc" }, { "ref": "wireless-networking/network-receiver.adoc" }, { "ref": "wireless-networking/network-transmitter.adoc" } ] }, { "title": "Autocrafting", "ref": "autocrafting/index.adoc", "children": [ { "ref": "autocrafting/getting-started-with-autocrafting.adoc" }, { "ref": "autocrafting/processing-recipes.adoc" }, { "ref": "autocrafting/keeping-items-in-stock.adoc" }, { "ref": "autocrafting/fluid-autocrafting.adoc" }, { "ref": "autocrafting/keeping-fluids-in-stock.adoc" }, { "ref": "autocrafting/autocrafting-with-filled-buckets.adoc" }, { "ref": "autocrafting/locking-and-unlocking.adoc" }, { "ref": "autocrafting/pattern-grid.adoc" }, { "ref": "autocrafting/pattern.adoc" }, { "ref": "autocrafting/crafter.adoc" }, { "ref": "autocrafting/crafting-monitor.adoc" }, { "ref": "autocrafting/crafter-manager.adoc" }, { "ref": "autocrafting/processing-pattern-encoder.adoc" } ] }, { "title": "Security", "ref": "security/index.adoc", "children": [ { "ref": "security/security-manager.adoc" }, { "ref": "security/security-card.adoc" } ] }, { "title": "Upgrades", "ref": "upgrades/index.adoc", "children": [ { "ref": "upgrades/upgrade.adoc" }, { "ref": "upgrades/range-upgrade.adoc" }, { "ref": "upgrades/speed-upgrade.adoc" }, { "ref": "upgrades/stack-upgrade.adoc" }, { "ref": "upgrades/crafting-upgrade.adoc" }, { "ref": "upgrades/regulator-upgrade.adoc" }, { "ref": "upgrades/fortune-upgrade.adoc" }, { "ref": "upgrades/silk-touch-upgrade.adoc" }, { "ref": "upgrades/interdimensional-upgrade.adoc" } ] }, { "title": "Utility", "ref": "utility/index.adoc", "children": [ { "ref": "utility/quartz-enriched-iron.adoc" }, { "ref": "utility/block-of-quartz-enriched-iron.adoc" }, { "ref": "utility/silicon.adoc" }, { "ref": "utility/cut-silicon.adoc" }, { "ref": "utility/wrench.adoc" }, { "ref": "utility/cutting-tool.adoc" }, { "ref": "utility/filter.adoc" }, { "ref": "utility/processor-binding.adoc" }, { "ref": "utility/raw-basic-processor.adoc" }, { "ref": "utility/raw-improved-processor.adoc" }, { "ref": "utility/raw-advanced-processor.adoc" }, { "ref": "utility/basic-processor.adoc" }, { "ref": "utility/improved-processor.adoc" }, { "ref": "utility/advanced-processor.adoc" }, { "ref": "utility/construction-core.adoc" }, { "ref": "utility/destruction-core.adoc" }, { "ref": "utility/machine-casing.adoc" }, { "ref": "utility/solderer.adoc" }, { "ref": "utility/cover.adoc" }, { "ref": "utility/hollow-cover.adoc" } ] }, { "title": "Advanced usage", "ref": "advanced-usage/index.adoc", "children": [ { "ref": "advanced-usage/commands.adoc" }, { "ref": "advanced-usage/profiling.adoc" }, { "ref": "advanced-usage/resource-packs.adoc" }, { "ref": "advanced-usage/translating-refined-storage.adoc" }, { "ref": "advanced-usage/using-development-builds.adoc" }, { "ref": "advanced-usage/using-the-api.adoc" } ] } ] ================================================ FILE: docs/pages/advanced-usage/commands.adoc ================================================ = Commands [cols="1,1"] |=== |Refined Storage version|Command |Explanation |v1.9.5 or higher |`/refinedstorage disk create `|Creates a disk for a player by disk ID. |v1.9.5 or higher |`/refinedstorage disk list`|Lists all disks on the server. |v1.9.5 or higher |`/refinedstorage disk list `|Lists all disks on the server, that the given player created. |v1.9.5 or higher |`/refinedstorage network list `|Lists all networks in a dimension, sorted by highest tick time first. |v1.9.5 or higher |`/refinedstorage network get `|Gets information about a network in a dimension and position. |v1.9.5 or higher |`/refinedstorage network get autocrafting list`|Gets all autocrafting tasks for a network. |v1.9.5 or higher |`/refinedstorage network get autocrafting get `|Gets a specific autocrafting task in a network. |v1.9.5 or higher |`/refinedstorage network get autocrafting cancel`|Cancels all autocrafting tasks in a network. |v1.9.5 or higher |`/refinedstorage network get autocrafting cancel `|Cancels a specific autocrafting task in a network. |v1.9.5 or higher |`/refinedstorage pattern dump`|Dumps information about the currently held xref:../autocrafting/pattern.adoc[]. Meant for debugging purposes. |v1.6.x |`/createdisk`|See <<_createdisk>>. |=== [#_createdisk] == `/createdisk` [.alert.alert-info] **** This command is only available for Minecraft 1.12.2 on Refined Storage version v1.6.x. **** Use the `/createdisk` command to spawn in a disk with a given ID. === Usage `/createdisk ` ==== Player The player name to give the disk to. ==== Item The item ID of the storage disk. For Refined Storage this would be `refinedstorage:storage_disk` (or `refinedstorage:fluid_storage_disk` for fluid disks). ==== Metadata The metadata value signifies the type of disk. **Items** [cols="1,1"] |=== |Disk type|Metadata value |1k|0 |4k|1 |16k|2 |64k|3 |Creative|4 |=== **Fluids** [cols="1,1"] |=== |Disk type|Metadata value |64k|0 |256k|1 |1024k|2 |4096k|3 |Creative|4 |=== ==== ID The ID parameter is the ID of the disk. A disk ID can be found by turning on advanced tooltips and checking the tooltip of the disk. ================================================ FILE: docs/pages/advanced-usage/index.adoc ================================================ = Advanced usage - xref:commands.adoc[] - xref:profiling.adoc[] - xref:resource-packs.adoc[] - xref:translating-refined-storage.adoc[] - xref:using-development-builds.adoc[] - xref:using-the-api.adoc[] ================================================ FILE: docs/pages/advanced-usage/profiling.adoc ================================================ = Profiling If 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. == Installing Sampler Sampler is a mod by Player that generates .nps files. You can download it from link:https://forum.industrial-craft.net/thread/10820[here]. === For Minecraft 1.12 link:http://files.player.to/sampler-1.73.jar[http://files.player.to/sampler-1.73.jar] === For Minecraft 1.11 link:http://files.player.to/sampler-1.72.1.jar[http://files.player.to/sampler-1.72.1.jar] === For Minecraft 1.10 link:http://files.player.to/sampler-1.69.3.jar[http://files.player.to/sampler-1.69.3.jar] == Running Sampler Then you can `/sampler start` and `/sampler stop` while it's lagging. Then 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. == Where to run Sampler? - Is it a performance on the server, like tick lag? Run Sampler *on the server*, NOT on your client! - Is it a performance on the client, like FPS lag? Run Sampler *on the client*, NOT on your server! ================================================ FILE: docs/pages/advanced-usage/resource-packs.adoc ================================================ = Resource packs == Color settings You can change the text colors that Refined Storage uses in its GUIs by changing the `pack.mcmeta` file. Example: [source,json] ---- { "pack": { "pack_format": 4, "description": "An example" }, "refinedstorage": { "primary_color": 11184810, "secondary_color": 11184810 } } ---- `primary_color` is used for the GUI titles, `secondary_color` is used for all the rest. The color is an integer representation of an RGBA color. ================================================ FILE: docs/pages/advanced-usage/translating-refined-storage.adoc ================================================ = Translating Refined Storage == How to create a translation Copy 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. == How to submit your translation * If you know Git well enough, you can contribute new language files via a pull request. * 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]. == Updating existing translations You 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. You can, of course, always diff manually using another tool, like the `diff` utility or an online diffing tool. ================================================ FILE: docs/pages/advanced-usage/using-development-builds.adoc ================================================ = Using development builds You can use development builds straight from GitHub. Follow the following steps: - Head to the link:https://github.com/refinedmods/refinedstorage/actions/workflows/build.yml[list of builds]. - Click on the commit that you want a build of. - Download "Artifacts". == Disclaimer - Using development builds is a risk! - It may contain untested code, bugs and crashes. - Remember to take backups. ================================================ FILE: docs/pages/advanced-usage/using-the-api.adoc ================================================ = Using the API == For Minecraft 1.18.2 or later Starting from Minecraft 1.18, you can include the Refined Storage API in your development environment from 2 sources: === GitHub packages Add the following repository to your `build.gradle`: [source,groovy] ---- repositories { maven { url = uri("https://maven.pkg.github.com/refinedmods/refinedstorage") credentials { username = "anything" password = "\u0067hp_oGjcDFCn8jeTzIj4Ke9pLoEVtpnZMP4VQgaX" } } } ---- The credentials are necessary because as of December 2021, GitHub packages still requires authentication for public packages. The password used is a personal access token that has read access to the Refined Mods repositories. It can be reused in other projects. See: * https://github.community/t/download-from-github-package-registry-without-authentication/14407/38 * https://github.community/t/download-from-github-package-registry-without-authentication/14407/44 You can find a list of versions on link:https://github.com/orgs/refinedmods/packages[GitHub packages]. === CreeperHost Maven Add the following repository to your `build.gradle`: [source,groovy] ---- repositories { maven { url = uri("https://maven.creeperhost.net") } } ---- You can find a list of versions on the link:https://maven.creeperhost.net/com/refinedmods/refinedstorage[Maven index]. **Warning:** Due to a bug in the Maven index on CreeperHost, new versions aren't included in the index. However, you can use them in your Gradle dependency. For 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. == For older Minecraft versions Some Refined Storage API versions for older Minecraft versions are available on the link:https://maven.creeperhost.net/com/refinedmods/refinedstorage[CreeperHost Maven]. However, not all of them are available. If you need a specific version, build Refined Storage yourself and include the API manually. == Including the API [source,groovy] ---- implementation fg.deobf("com.refinedmods:refinedstorage:VERSION_HERE") { transitive false } ---- == Using the API Use the `@RSAPIInject` annotation to get access to the API facade. [source,java] ---- public class MyMod { @RSAPIInject public static IRSAPI RSAPI; } ---- == Javadoc Updated Javadoc is available after every release link:https://refinedmods.com/javadoc/refinedstorage[here]. ================================================ FILE: docs/pages/autocrafting/autocrafting-with-filled-buckets.adoc ================================================ = Autocrafting with filled buckets Some crafting recipes may require a filled fluid bucket. To use fluids from your fluid storage to fill buckets, you can set up a xref:pattern.adoc#_processing[processing pattern] that has following inputs: - 1 empty bucket - 1000 mB of the fluid of your choice For the output: - 1 filled bucket Put 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]). Refined Storage will output the fluid from your fluid storage, and, an empty bucket. It is up to the external machine to fill it. ================================================ FILE: docs/pages/autocrafting/crafter-manager.adoc ================================================ = Crafter Manager :icon: crafter-manager.png :from: v1.5.33 The Crafter Manager is a block that allows you to see all your xref:pattern.adoc[patterns] in one GUI. == Naming All the xref:pattern.adoc[patterns] are listed and categorized per xref:crafter.adoc[]. The categorization is based on the name of the xref:crafter.adoc[]. To decide which name a xref:crafter.adoc[] gets, the following rules (in order) are used: 1. If the xref:crafter.adoc[] is renamed with a Minecraft link:https://minecraft.gamepedia.com/Anvil[Anvil], use that name 2. If the xref:crafter.adoc[] is connected to a machine in the world, use the name of that machine 3. Use "Crafter" as name == Sizes One can configure the Crafter Manager size: - Stretched (default) - Small - Medium - Large When choosing the stretched size, the Crafter Manager will take up all the vertical screen space. This can be limited through the `maxRowsStretch` config option. include::../../partials/search-box.adoc[] include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/autocrafting/crafter.adoc ================================================ = Crafter :icon: crafter.png :from: v0.6.0-alpha The {doctitle} is a block that crafts items with xref:pattern.adoc[patterns]. It can take xref:../upgrades/speed-upgrade.adoc[speed upgrades] to increase the crafting speed. With processing xref:pattern.adoc[patterns], the {doctitle} has to face the correct input side of the machine. [#_chaining] == Chaining A {doctitle} can be chained by letting them face each other. This is useful when connecting a {doctitle} to a single machine. When 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. == {doctitle} modes The {doctitle} has 4 modes: - Ignore redstone signal (default) - Redstone signal unlocks autocrafting - Redstone signal locks autocrafting - Redstone pulse inserts next set The (un)locking mechanism is used to block the {doctitle}, so it can't insert items or fluids into the connected inventory. "Blocking mode" can be achieved with the "Redstone pulse inserts next set" mode. See xref:locking-and-unlocking.adoc[] for more details. include::../../partials/recoloring.adoc[] == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] ================================================ FILE: docs/pages/autocrafting/crafting-monitor.adoc ================================================ = Crafting Monitor :icon: crafting-monitor.png :from: v0.6.0-alpha The {doctitle} is a block that shows all the current running crafting tasks and how long they have been running. Each crafting task can be cancelled manually. It is also possible to cancel all crafting tasks at once. Per task, it shows a grid of cells, each containing information about how an item or fluid is used in the crafting task. This is what the terminology in those cells mean: - Stored: the item or fluid is stored in the internal inventory of the crafting task, and will be used later on - Missing: the crafting task cannot continue without this item or fluid as it's missing - Processing: the item or fluid displayed is currently inserted into an external machine and is processing - Scheduled: the item or fluid is scheduled to be made by inserting it's ingredients in an external machine later - Crafting: this item is being crafted (regular crafting, not processing) == Sizes The size of any {doctitle} can be configured as well: - Stretched (default) - Small - Medium - Large When choosing the stretched size, the {doctitle} will take up all the vertical screen space. This can be limited through the `maxRowsStretch` config option. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/autocrafting/fluid-autocrafting.adoc ================================================ = Fluid autocrafting So far you've set up autocrafting for items. Since 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. Every autocrafting pattern that uses fluids is a processing pattern. If 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[]. With 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. This means that you can also declare fluids as an output in the processing pattern. It also means that you can request fluids from the xref:../viewing-resources/fluid-grid.adoc[]. You can mix fluid and item inputs/outputs freely. == Creation of the mixed pattern To make a mixed (fluid or item) processing pattern, toggle the xref:pattern-grid.adoc[] in fluid or item mode. You can then use link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] transfer to transfer item and fluid ingredients. You can also use a filled fluid container (like a bucket) to specify the fluid. Use left or right click on the fluid slot to modify the millibuckets (mB). == Other resources - link:https://www.youtube.com/watch?v=6v-e_NdLEnI[Demo video] ================================================ FILE: docs/pages/autocrafting/getting-started-with-autocrafting.adoc ================================================ = Getting started with autocrafting == What is autocrafting? Autocrafting is automated crafting through Refined Storage. You 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. Instead of manually moving items in the crafting matrix, you can make Refined Storage do all the work. == Patterns To teach Refined Storage a recipe to craft we use a xref:pattern-grid.adoc[]. This xref:pattern-grid.adoc[] creates xref:pattern.adoc[patterns]. A xref:pattern.adoc[] contains the recipe of the item you want to craft. == Pattern dependencies You need to create a xref:pattern.adoc[] for each sub-item you want automatically crafted. Refined 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. If 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. == Example You want to autocraft link:https://minecraft.gamepedia.com/Chest[chests]. - Create a xref:pattern.adoc[] for the chest - Create a xref:pattern.adoc[] for the wooden planks that are used to craft the chest - If you don't create the pattern, and you have wooden planks, than Refined Storage will be able to use those - If you run out of planks, Refined Storage will not know what to do - 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 == Exact mode Exact mode is turned on by default which means every xref:pattern.adoc[] is an "exact pattern". This means Refined Storage takes items exactly as defined in the xref:pattern.adoc[] When Exact mode is turned off it will also match for other acceptable inputs for that crafting recipe (other types of wood, etc). == Crafters Once you created your xref:pattern.adoc[patterns], craft a xref:crafter.adoc[] and connect it to your storage network. In those xref:crafter.adoc[crafters] you'll store all your xref:pattern.adoc[patterns]. == Requesting an item As 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[]. You can do this by clicking on the item you want to autocraft. If 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. When requesting an item, Refined Storage will first ask how many of that item you want to craft. Then, it will show you what items it will take or craft. You can't start an autocrafting task if you have insufficient resources, unless you have the ability to autocraft those resources. == How autocrafting works internally Initially, 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). All further actions to those items are performed in the internal storage, so the network doesn't "see" any changes while the task is running. Because all the subcrafts are done in the internal storage, the storage network can not "steal" items from autocrafting tasks. When 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. That is prioritized. If the autocrafting task deems the item or fluid as necessary, it will be intercepted and the storage network will receive nothing. == Monitoring your crafting tasks Craft a xref:crafting-monitor.adoc[] and connect it to your storage network to see how the crafting task is progressing. You can also cancel autocrafting tasks from there. You can also use a xref:../wireless-networking/wireless-crafting-monitor.adoc[] to see the running crafting tasks remotely from your inventory. == Managing your patterns in a convenient way Want a convenient way to access all your xref:pattern.adoc[patterns] in the xref:crafter.adoc[crafters] of your storage network? Use the xref:crafter-manager.adoc[]. == Speeding up your crafting tasks Insert xref:../upgrades/speed-upgrade.adoc[speed upgrades] in the xref:crafter.adoc[crafters]. ================================================ FILE: docs/pages/autocrafting/index.adoc ================================================ = Autocrafting - xref:getting-started-with-autocrafting.adoc[] - xref:processing-recipes.adoc[] - xref:keeping-items-in-stock.adoc[] - xref:fluid-autocrafting.adoc[] - xref:keeping-fluids-in-stock.adoc[] - xref:autocrafting-with-filled-buckets.adoc[] - xref:locking-and-unlocking.adoc[] - xref:pattern-grid.adoc[] - xref:pattern.adoc[] - xref:crafter.adoc[] - xref:crafting-monitor.adoc[] - xref:crafter-manager.adoc[] - xref:processing-pattern-encoder.adoc[] ================================================ FILE: docs/pages/autocrafting/keeping-fluids-in-stock.adoc ================================================ = Keeping fluids in stock Keeping fluids in stock work the same way as xref:keeping-items-in-stock.adoc[keeping items in stock]. Create a xref:../input-and-output/fluid-interface.adoc[] with a xref:../upgrades/crafting-upgrade.adoc[] in it. Then, specify the fluid that you want to keep in stock by clicking a fluid container (like a bucket) in the "out" slot. You can change the amount by left or right clicking on the fluid. The fluids will now be autocrafted if needed. To 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[]. Put the xref:../storage/external-storage.adoc[] in fluid mode. Make sure the xref:../storage/external-storage.adoc[] is in "extract-only" mode. That 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. ================================================ FILE: docs/pages/autocrafting/keeping-items-in-stock.adoc ================================================ = Keeping items in stock Create an xref:../input-and-output/interface.adoc[] with a xref:../upgrades/crafting-upgrade.adoc[] in it. Then, specify the items that you want to keep in stock. The items will now be autocrafted if needed. To 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[]. Make sure the xref:../storage/external-storage.adoc[] is in "extract-only" mode. That way, Refined Storage won't attempt to insert items in the xref:../input-and-output/interface.adoc[] that is meant for keeping in stock. ================================================ FILE: docs/pages/autocrafting/locking-and-unlocking.adoc ================================================ = Locking and unlocking :from: v1.6.6 The xref:crafter.adoc[] in Refined Storage supports locking mechanisms. Locking and unlocking a xref:crafter.adoc[] only applies to processing recipes. The locking and unlocking functionality also has to be enabled by configuring the xref:crafter.adoc[] mode. == Crafter modes === Ignore redstone signal (default) Ignores redstone signals. This is the default. === Redstone signal locks autocrafting - If a xref:crafter.adoc[] is locked, it can't insert items or fluids to the connected inventory. - If a xref:crafter.adoc[] is unlocked, it can insert items or fluids to the connected inventory. === Redstone signal unlocks autocrafting This is the opposite of the "Redstone signal locks autocrafting" mode. === Redstone pulse inserts next set This mode was primarily introduced to support a concept called "blocking mode". Blocking mode is primarily utilised for processing recipes, where the machine that does the processing can only handle 1 recipe at a time. If the xref:crafter.adoc[] is in "Redstone pulse inserts next set" mode, this is the flow: - The xref:crafter.adoc[] will automatically go in an unlocked state - 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[] - The xref:crafter.adoc[] now goes in a locked state, and it won't push out any more items and fluids - The xref:crafter.adoc[] will stay locked until it receives a redstone pulse When you apply a redstone pulse: - The xref:crafter.adoc[] will unlock itself - The xref:crafter.adoc[] pushes the next set of items and fluids, if any - If there were any items and fluids to push, the xref:crafter.adoc[] will lock itself again Generally, you'd apply a redstone signal if the recipe you're processing has completed. It is up to the player to handle that. == Common mistakes with "Redstone pulse inserts next set" - Wrong redstone flow causes the xref:crafter.adoc[] to lock when it is supposed to unlock - 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 === Crafter deadlock If 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: - If the xref:../input-and-output/importer.adoc[] imports too fast AND - the comparator doesn't pick up the item being in the chest AND - by not picking up the item, thus, not sending out a redstone signal You'd cause a deadlock because the xref:crafter.adoc[] doesn't receive a redstone pulse, and the xref:crafter.adoc[] would keep waiting forever. The 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[]. Use the xref:../input-and-output/importer.adoc[] redstone settings to achieve this. == Other resources - link:https://www.youtube.com/watch?v=c9s-IfDPKxw[Demo video] ================================================ FILE: docs/pages/autocrafting/pattern-grid.adoc ================================================ = Pattern Grid :icon: pattern-grid.png :from: v0.6.0-alpha The {doctitle} is the same as a regular xref:../viewing-resources/grid.adoc[], but also allows for the creation of xref:pattern.adoc[patterns]. == Mode By default, the {doctitle} creates regular crafting xref:pattern.adoc[patterns]. To create processing xref:pattern.adoc[patterns], toggle the "processing" checkbox. == Allowed tags The 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. These tags are retrieved from link:https://minecraft.gamepedia.com/Tag[Minecraft's tag system]. You can specify the allowed tags in the {doctitle}. To 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. Items 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. You can also define valid alternatives by clicking on the item or fluid and then clicking on "Alternatives". == Ore dictionary (Refined Storage v1.6.x or lower only) To create ore dictionary sensitive xref:pattern.adoc[patterns], toggle the "oredict" checkbox. == Modifying a pattern You can re-insert a xref:pattern.adoc[] in the output slot to modify and (possibly) override it. == Recipe transferring The {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring. You don't necessarily need the actual items in your storage network to create a xref:pattern.adoc[] for it. Refined Storage will notify you when you have a xref:pattern.adoc[] for an item configured when transferring a recipe. == Manual input/output configuration Click an item or fluid in the slots to configure the xref:pattern.adoc[]. Click on the item or fluid to change the quantity. Use CTRL + click to modify the allowed tags for the input slot (Minecraft 1.14.4 and above). Use shift to clear the slot. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/autocrafting/pattern.adoc ================================================ = Pattern :icon: pattern.png :from: v0.6.0-alpha A {doctitle} is an item that is used in autocrafting. It stores the recipe that should be autocrafted. A recipe can be assigned with the xref:pattern-grid.adoc[] and the {doctitle} is stored in a xref:crafter.adoc[]. [#_processing] == Processing If the {doctitle} is in processing mode, it will push the inputs to the connected inventory of the xref:crafter.adoc[]. == Exact mode (patterns in crafting mode) Exact mode is turned on by default which means every {doctitle} is an "exact pattern". This means Refined Storage takes items exactly as defined in the {doctitle}. When Exact mode is turned off it will also match for other acceptable inputs for that crafting recipe. Exact mode can't be set for patterns in processing mode. For processing mode, see the section about allowed tags. == Allowed tags (patterns in processing mode) The 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. These tags are retrieved from link:https://minecraft.gamepedia.com/Tag[Minecraft's tag system]. You can specify the allowed tags in the xref:pattern-grid.adoc[]. == Ore dictionary mode (Refined Storage v1.6.x or lower only) The {doctitle} can be configured to be an ore dictionary pattern. Instead of extracting the exact item, it'll try to extract equivalent items according to the ore dictionary as well. == Clearing Use SHIFT + right click in your inventory while holding the {doctitle} to clear it. You can also override the {doctitle} in the xref:pattern-grid.adoc[]. == Modifying You can re-insert a {doctitle} in the output slot of the xref:pattern-grid.adoc[] to modify and (possibly) override it. ================================================ FILE: docs/pages/autocrafting/processing-pattern-encoder.adoc ================================================ = Processing Pattern Encoder :icon: processing-pattern-encoder.png :from: v0.6.0-alpha :to: v1.5.6 [.alert.alert-warning] **** The {doctitle} has been removed in v1.5.6 and its functionality has been moved to the xref:pattern-grid.adoc[]. **** A {doctitle} is used to create xref:pattern.adoc[patterns] meant for machine automation. It takes up to 9 inputs and 9 outputs, so the storage network knows what to take and what to expect. This block can't be connected to a storage network. == Recipe transferring The {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring. When using this, Refined Storage will use the inputs and outputs that the link:https://minecraft.curseforge.com/projects/jei[JEI] recipe has. ================================================ FILE: docs/pages/autocrafting/processing-recipes.adoc ================================================ = Processing recipes == What are processing recipes? So far, in xref:getting-started-with-autocrafting.adoc[] you learnt how to automate regular crafting recipes. What if you want to automate the creation of items that don't involve a crafting recipe, like ores to ingots in a furnace? For this you use processing xref:pattern.adoc[patterns]. == Processing patterns You can create processing xref:pattern.adoc[patterns] in the xref:pattern-grid.adoc[] by toggling the "processing" checkbox. The GUI will change and it'll allow you to define up to 9 inputs and outputs. - Inputs is what Refined Storage will extract from your storage network. - Outputs are what Refined Storage expects back in the network when the item has processed. == Example Let'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]. - In the input section you put 1 link:https://minecraft.gamepedia.com/Iron_Ore[Iron Ore]. - In the output section you put 1 link:https://minecraft.gamepedia.com/Iron_Ingot[Iron Ingot]. == Inserting the pattern Make a xref:crafter.adoc[] and let it face the machine in a way it can input it in the correct slot. Insert the processing xref:pattern.adoc[] you just created in the xref:crafter.adoc[] facing the machine. When you now request the item, Refined Storage will insert the inputs in the machine. You do need to get the item manually back in the storage network so Refined Storage knows that the item has been processed. You 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[]. == Allowed tags The 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. These tags are retrieved from Minecraft's tag system. You can specify the allowed tags in the xref:pattern-grid.adoc[]. == Chaining crafters You can xref:crafter.adoc#_chaining[chain crafters] to connect multiple xref:crafter.adoc[crafters] to the same machine. ================================================ FILE: docs/pages/faq.adoc ================================================ = Frequently asked questions (FAQ) == I have an idea for a feature that can be toggled on or off with an config option! Refined Storage doesn't do config options for features or things that change behavior in general. Why not? - The experience players have with Refined Storage can differ between modpacks and that can be confusing - Issues will be created by players wondering why their favorite feature doesn't work in modpack A, but does in modpack B - Putting features or behaviors behind a config option makes it harder to maintain - With bug reports we'd have to ask if the feature is toggled on or off in the config - Bugs might get noticed later since it's behind a config option and thus less visible == Not including "X" in Refined Storage makes this mod useless when mods like "Y" aren't installed! The 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. If other mods are required to achieve something, that isn't a problem. Examples: - Autocrafting needs an external bucket filling machine in order to convert fluids to buckets - Energy that Refined Storage uses needs to be generated with another mod == What is the difference between Refined Storage and Applied Energistics? Refined Storage is the simpler of the two and was heavily based off of AE1. AE2 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. A 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. == Can I use this mod in my private/public mod pack? Yes, you don't need to ask permission. == Can I connect Refined Storage to my Applied Energistics 2 system, or vice-versa? No, you can't. You might've found an issue on our issue tracker that says you can, but no, you can't. == Is there a Refined Storage for MC 1.7.10? No, there isn't. == Will you make a Refined Storage for MC 1.7.10? No, I won't. == Is there a way to have infinite Wireless Transmitter range? It's not possible if you're using the base Refined Storage mod, or Refined Storage Addons. You'll have to find an addon mod which does add such functionality. Alternatively, you can increase the range in the Refined Storage config file to be infinite. == Is there a way to request autocrafting in the Grid if I already have the item or fluid? Yes! There are many helpful key and mouse bindings for the xref:viewing-resources/grid.adoc#_controls[grid]. == I found an issue/bug with Refined Storage! Head over to our link:https://github.com/refinedmods/refinedstorage/issues[issue tracker on GitHub] and report it there. ================================================ FILE: docs/pages/getting-started.adoc ================================================ = Getting started == Core concepts Refined Storage is a storage mod where you can build a storage network made up of devices. Those devices manipulate your storage. In this tutorial: - You'll craft a xref:storage/disk-drive.adoc[]. A xref:storage/disk-drive.adoc[] can contain item or fluid storage disks. Those disks will provide your storage network with storage. If you insert or extract an item, it will use the data on your disks. - You'll craft a xref:viewing-resources/grid.adoc[]. Through that block, you can modify your storage (which will modify the data on your disks). - Before crafting any of these devices, you'll first craft a xref:networking/controller.adoc[], which ties the entire network together. == A minimal setup === Step 0: Install Refined Storage (if necessary) Ensure that the modpack that you are playing contains Refined Storage. You can validate this by checking the modlist of your modpack. If 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]. It might also be helpful to know that Refined Storage xref:how-to-install.adoc#_optional_dependencies[has integration with various other mods]. === Step 1: The Controller Craft the xref:networking/controller.adoc[]. The xref:networking/controller.adoc[] is the "core" of your storage network. You'll be connecting all the Refined Storage devices to this block. The xref:networking/controller.adoc[] needs energy. More specifically, Forge Energy or RF. Lots of mods that generate energy support this. === Step 2: Storage and accessing your items Craft a xref:storage/disk-drive.adoc[] and a xref:storage/1k-storage-disk.adoc[] to store your items. You 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. Put 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. Connect 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. === Step 3: Viewing your storage You are now able to insert and extract items in the xref:viewing-resources/grid.adoc[]. == Disks in block form You can also use the various xref:storage/index.adoc#_storage_blocks[storage blocks] instead of xref:storage/index.adoc#_storage_disks[storage disks]. ================================================ FILE: docs/pages/how-to-install.adoc ================================================ = How to install Installing Refined Storage is the same as for any other Forge mod. == Setting up Forge You'll need a working Forge instance to use Refined Storage. You can use launchers like MultiMC or even the vanilla launcher to do this. Instructions for setting up a Forge instance are plenty online and are out of scope for this wiki. == Downloading the mod Download a Refined Storage `.jar` file for your Minecraft version from official sources: - link:https://www.curseforge.com/minecraft/mc-mods/refined-storage[CurseForge] - link:https://modrinth.com/mod/refined-storage[Modrinth] - link:https://github.com/refinedmods/refinedstorage/releases[GitHub] == Installing the mod Once you have the `.jar` file, place it in the `mods/` directory of your Forge instance. You may have to start up your instance at least once so Forge can autogenerate the `mods/` directory. == CurseForge/Twitch launcher When 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. == Configuring the mod Changing the configuration isn't needed in most cases. If you need to do this, you can: - Change server-specific configuration in `saves//serverconfig/refinedstorage-server.toml` - Change client-specific configuration in `config/refinedstorage-client.toml` Note that server-specific configuration also applies to single player worlds. That is because when you're playing single player, Minecraft uses an internal server. [#_optional_dependencies] == Optional dependencies Refined Storage can work perfectly by itself without any additional mods, but it's helpful to install a few other mods alongside it. - **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. - **A mod that can generate Forge Energy (also known as FE or RF):** A Refined Storage network requires energy to run. If 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"). Change `useEnergy` under `[controller]` to `false`. - **link:https://www.curseforge.com/minecraft/mc-mods/crafting-tweaks[Crafting Tweaks]** - **link:https://www.curseforge.com/minecraft/mc-mods/curios[Curios]** - **link:https://www.curseforge.com/minecraft/mc-mods/inventory-sorter[Inventory Sorter]** Until Minecraft 1.14, xref:opencomputers-api.adoc[Refined Storage had integration with OpenComputers]. ================================================ FILE: docs/pages/index.adoc ================================================ = Refined Storage ================================================ FILE: docs/pages/index.html ================================================

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.


Items 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.

This 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.

Get started

Need help?

Join our Discord server for community support.

Join our Discord server

Found a problem?

Issues can be reported on our issue tracker.

Refined Storage on GitHub

Want to stay up to date?

Follow us on X to stay up to date with Refined Mods news and releases.

Follow @refinedmods on X
================================================ FILE: docs/pages/input-and-output/constructor.adoc ================================================ = Constructor :icon: constructor.png :from: v0.3.0-alpha The {doctitle} places items or fluids from the storage network in the world. No 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). The {doctitle} can also drop items in the world instead of placing actual blocks. When provided with a xref:../upgrades/stack-upgrade.adoc[], it'll drop stacks of items at a time. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] - xref:../upgrades/crafting-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/destructor.adoc ================================================ = Destructor :icon: destructor.png :from: v0.3.0-alpha The {doctitle} destroys blocks or fluids in front of it and puts the drops in the storage network. The {doctitle} has the ability to only break certain blocks or fluids, with the whitelist and blacklist option. Said whitelist and blacklist can be NBT or damage sensitive. The {doctitle} can also pick up items in the world instead of destroying blocks. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/fortune-upgrade.adoc[] - xref:../upgrades/silk-touch-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/disk-manipulator.adoc ================================================ = Disk Manipulator :icon: disk-manipulator.png :from: v1.0.5 The {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. == Whitelist or blacklist The player can configure the {doctitle} to have a certain whitelist or blacklist of items that can be transferred. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Mode The player can also choose whether to insert items to the storage network or extract items from the storage network. include::../../partials/recoloring.adoc[] == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/exporter.adoc ================================================ = Exporter :icon: exporter.png :from: v0.3.0-alpha The {doctitle} extracts items or fluids from the storage network and inserts it in the inventory or tank in front of it. Before being able to export anything, the player has to choose the items or fluids to export. The chosen items can be configured to be NBT or damage sensitive. The {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. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] - xref:../upgrades/crafting-upgrade.adoc[] - xref:../upgrades/regulator-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/fluid-interface.adoc ================================================ = Fluid Interface :icon: fluid-interface.png :from: v0.9.0-beta The {doctitle} is the same as an xref:interface.adoc[] but for fluids. It has 2 internal tanks, one for input and one for output. == Input slot The {doctitle} has an input slot to import the contents of fluid containers (like a filled bucket). You can also interact with the input tank by using pipes from other mods. == Output configuration - Click a fluid container (like a filled bucket) in the "Out" slot to configure the output fluid. - Use left or right click on the fluid to change the mB amount. - Use shift to clear the fluid slot. - You can also interact with the output tank by using pipes from other mods. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] - xref:../upgrades/crafting-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/getting-items-in-and-out.adoc ================================================ = Getting items in and out So far, you know xref:../getting-started.adoc[how to add storage disks to your network and view them]. But how do you get those items in and out in an automated way? This is a quick overview of all the devices that manipulate your storage. == Exporter If 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. Configure the filter slots of the xref:exporter.adoc[] to the items you want to export. == Importer If 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. == Interface Want the best of both worlds? Use an xref:interface.adoc[] to get importing and exporting functionality in one block. == Constructor To place blocks from your storage network in the world, use an xref:constructor.adoc[]. Configure the filter slots of the xref:constructor.adoc[] to the block you want to place. == Destructor To destroy and insert blocks from the world into your storage, use an xref:destructor.adoc[]. You can configure a whitelist or blacklist of blocks to destroy. == Disk Manipulator If you want to import from disks or export to a disk from the network, use a xref:disk-manipulator.adoc[]. ================================================ FILE: docs/pages/input-and-output/importer.adoc ================================================ = Importer :icon: importer.png :from: v0.3.0-alpha The {doctitle} imports items or fluids from an inventory in front of the block and inserts it in the storage network (if there is space). By 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. == Whitelist and blacklist There is also a whitelist and blacklist option to only allow or forbid some items from entering the storage network. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/index.adoc ================================================ = Input and output - xref:getting-items-in-and-out.adoc[] - xref:importer.adoc[] - xref:exporter.adoc[] - xref:constructor.adoc[] - xref:destructor.adoc[] - xref:interface.adoc[] - xref:fluid-interface.adoc[] - xref:disk-manipulator.adoc[] - xref:reader.adoc[] - xref:writer.adoc[] ================================================ FILE: docs/pages/input-and-output/interface.adoc ================================================ = Interface :icon: interface.png :from: v0.4.0-alpha The Interface is a block that acts as a combination of the xref:importer.adoc[] and the xref:exporter.adoc[]. == Importing Let's talk about the difference between an xref:importer.adoc[] and the Interface for importing. The xref:importer.adoc[] needs to be connected to an inventory to import items or fluids. It has no internal inventory and you can't insert items directly to the xref:importer.adoc[. In comparison with the xref:importer.adoc[] the Interface has an internal inventory to receive items and import them (through piping, hoppers, etc). That internal inventory is accessible by opening the GUI and looking at the slots under "Interface Import"). The Interface does NOT extract items from adjacent inventories automatically, you have to actually insert them in the Interface through piping, hoppers, etc. == Exporting There is also an option for exporting items from the system. These items can be piped out through a piping system from another mod, hoppers, etc. It can be configured to be NBT or damage sensitive. == Output configuration - Click an item in the export slots to configure that to be exported. - Use left or right click on the item to change the amount. - Use shift to clear the slot. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] - xref:../upgrades/stack-upgrade.adoc[] - xref:../upgrades/crafting-upgrade.adoc[] ================================================ FILE: docs/pages/input-and-output/reader.adoc ================================================ = Reader :icon: reader.png :from: v1.4.0-beta :to: v1.7.0-alpha [.alert.alert-warning] **** The {doctitle} has been removed in version v1.7.0-alpha. **** A Reader has the ability to manage {doctitle} / xref:writer.adoc[] channels on a network. The {doctitle} is a block that takes items, fluids, energy and / or a redstone signal. The data will be transmitted to the configured channel and can be read out with a xref:writer.adoc[]. The {doctitle} doesn't auto-extract any of the supported types (with an exception to redstone signals). You have to insert it manually. == Supported types - Items - Fluids - Energy - Redstone ================================================ FILE: docs/pages/input-and-output/writer.adoc ================================================ = Writer :icon: writer.png :from: v1.4.0-beta :to: v1.7.0-alpha [.alert.alert-warning] **** The {doctitle} has been removed in version v1.7.0-alpha. **** A {doctitle} has the ability to manage xref:reader.adoc[] / {doctitle} channels on a network. The {doctitle} is a block that exposes items, fluids, energy and / or a redstone signal from the bound channel. The data that is received is sent from the xref:reader.adoc[]. The {doctitle} doesn't auto-push any of the supported types (with an exception to redstone signals). You have to extract it manually. == Supported types - Items - Fluids - Energy - Redstone ================================================ FILE: docs/pages/need-help.adoc ================================================ = Need help? == Supported versions Before creating an issue on our issue tracker, ensure that your version is still supported. [cols="1,1,1,1,1"] |=== |Minecraft version|Refined Storage version range|State|New features|Bugfixes |Minecraft 1.20.x|v1.12.x - v1.13.x|Maintained|❌|✔️ |Minecraft 1.19.x|v1.11.x|Maintained|❌|✔️ |Minecraft 1.18.x|v1.10.x|Maintained|❌|✔️ |Minecraft 1.17.x|-|Never available|❌|❌ |Minecraft 1.16.x|v1.9.x|Unmaintained|❌|❌ |Minecraft 1.15.x|v1.8.x|Unmaintained|❌|❌ |Minecraft 1.14.x|v1.7.x |Unmaintained|❌|❌ |Minecraft 1.13.x|-|Never available|❌|❌ |Minecraft 1.12.x|v1.5.x - v1.6.x|Unmaintained|❌|❌ |Minecraft 1.11.x|v1.3.x - v1.4.x|Unmaintained|❌|❌ |Minecraft 1.10.x|v0.8.x - v1.2.x|Unmaintained|❌|❌ |Minecraft 1.9.x|v0.3.x - v0.7.x|Unmaintained|❌|❌ |Minecraft 1.8.x|-|Never available|❌|❌ |Minecraft 1.7.x|-|Never available|❌|❌ |=== Refined Storage v1.x will not be gaining new features as we are building link:https://github.com/refinedmods/refinedstorage2[Refined Storage 2]. ================================================ FILE: docs/pages/need-help.html ================================================

Have a question?

Join our Discord server for community support.

Join our Discord server

Found a bug, crash or other problem?

Issues can be reported on our issue tracker.

Refined Storage on GitHub

Want to stay up to date?

Follow us on X to stay up to date with Refined Mods news and releases.

Follow @refinedmods on X
================================================ FILE: docs/pages/networking/cable.adoc ================================================ = Cable :from: v0.3.0-alpha :icon: cable.png {doctitle} is used to connect devices to the xref:controller.adoc[]. They are not always necessary, as long as the devices are next to each other in any direction a connection will be established as well. ================================================ FILE: docs/pages/networking/controller.adoc ================================================ = Controller :from: v0.3.0-alpha :icon: controller.png The {doctitle} is the core of the Refined Storage network. You need to connect all the Refined Storage devices to this block. == Connecting devices You are supposed to connect every device that depends on the storage network connection to the {doctitle}. You can connect devices with xref:cable.adoc[cables]. xref: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. == Energy The {doctitle} accepts and consumes Forge Energy (FE). Most mods have a way to generate energy, therefore Refined Storage doesn't come by itself with a way to generate energy. - The energy is extracted per tick. - The amount of energy that is extracted depends on the amount of devices, and which devices. - Every device type consumes another amount of energy. - You can see how many energy each device consumes by right clicking the {doctitle}. If the {doctitle} runs out of energy, the network will be turned off until there is sufficient energy provided again. When the {doctitle} is broken, it will maintain its energy. == Limits Each Refined Storage network can only have a single {doctitle}. It doesn't make sense to connect multiple controllers on the same network. If you connect another {doctitle} to an already existing network, the {doctitle} will break as an item in the world. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/networking/creative-controller.adoc ================================================ = Creative Controller :from: v0.3.0-alpha :icon: controller.png The {doctitle} is the same as a regular xref:controller.adoc[] but has infinite energy. It can only be obtained in creative mode. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/networking/detector.adoc ================================================ = Detector :icon: detector.png :from: v0.3.0-alpha The {doctitle} is a block that emits a redstone signal if an item, or fluid count matches a given amount. It is also possible to be NBT or damage sensitive. == Types of criteria [cols="1,1"] |=== |Criteria|Explanation |<|Emits a signal when lower than the given amount |>|Emits a signal when higher than the given amount |=|Emits a signal when equal to the given amount |=== == Checking the total count in the storage When 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. == Amounts in fluid mode When the {doctitle} is in fluid mode, the amount given is in millibuckets (mB). If you want to check for 1 bucket of a fluid, use 1000, not 1. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/networking/index.adoc ================================================ = Networking - xref:controller.adoc[] - xref:creative-controller.adoc[] - xref:cable.adoc[] - xref:detector.adoc[] - xref:relay.adoc[] ================================================ FILE: docs/pages/networking/relay.adoc ================================================ = Relay :from: v0.4.0-alpha :icon: relay.png The Relay acts as xref:cable.adoc[], but can be turned on or off depending on the redstone configuration. Devices connected after the Relay will be on or off depending if the {doctitle} is on. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/news/20210518-announcing-refined-storage-2.adoc ================================================ = Announcing Refined Storage 2 :type: article :description: A new major version of Refined Storage is in the works. :date: 2021-05-18 Since 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. The 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. The 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. I'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. Rewriting 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. The mod is being rewritten with an enhanced focus on quality (that's why it is taking so long!) and to be modloader independent. In 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. Because 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. ================================================ FILE: docs/pages/news/20220704-a-big-milestone-for-refined-storage-2.adoc ================================================ = A big milestone for Refined Storage 2 :type: article :description: The first milestone for Refined Storage 2 has been completed. :date: 2022-07-04 After 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]. Finishing the first milestone is a big deal. Important architectural decisions have been made to lay a solid foundation for further milestones and content. You can track the progress in the following locations: * link:https://github.com/orgs/refinedmods/projects/6[The project board] * link:https://github.com/refinedmods/refinedstorage2/milestones[The list of milestones] * link:https://github.com/refinedmods/refinedstorage2[The GitHub repository] ================================================ FILE: docs/pages/news/20230707-a-week-of-modding.adoc ================================================ = A week of modding :type: article :description: A week of modding for Refined Storage 1.x, Refined Storage Addons, and Ranged Pumps. :date: 2023-07-07 This week was an important one for Refined Storage 1.x, Refined Storage Addons, and Ranged Pumps: * They got ported to Minecraft 1.20.1 * link:https://modrinth.com/user/raoulvdberge[They are now available on Modrinth as well] * 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!) * link:https://github.com/refinedmods/refinedstorage/blob/develop/CHANGELOG.md[The historical changelogs got updated to the Keep A Changelog format] * 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] Actually using Refined Architect on our projects only took a week, but the planning, pre-work, and testing with Refined Storage 2 took many weeks. Along 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]. The next plans are: * Release a Fabric port of Ranged Pumps * Potentially port Refined Pipes to Minecraft 1.20.1 * Keep on working on Refined Storage 2, link:https://github.com/orgs/refinedmods/projects/6/views/7[in which Milestone 2 is nearing completion] ================================================ FILE: docs/pages/news/20230819-refined-storage-2-milestone-2-completed.adoc ================================================ = Refined Storage 2 - milestone 2 completed! :type: article :description: Milestone 2 for Refined Storage 2 has been completed. :date: 2023-08-19 Today, *milestone 2* for Refined Storage 2 has been completed! image::../../assets/news/20230819-refined-storage-2-milestone-2-completed.png[Screenshot showing how milestone 2 is completed on GitHub] link:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[_If you don't know what Refined Storage 2 is, please read the FAQ first._] [.underline.bold]#Milestone 2 brings a lot of essential features:# * Importer * Exporter * Upgrades * Interface * External Storage * Support for multiple resource types in a single Grid * Colored cables * Crafting Grid * Detector * Constructor * Destructor * Additional JEI/REI integrations Additionally, some features have been reworked or improved in comparison with Refined Storage 1.x. Some statistics: * Milestone 2 was in development from June 22nd, 2022 to August 19th, 2023. + That is little over a year! _(milestone 1 was in development from October 24th, 2020 to June 22nd, 2022 - almost 2 years)_ * Milestone 2 had 63 closed issues _(milestone 1 had 61 closed issues)_ * Milestone 2 had 15 releases _(milestone 1 had 5 releases)_ [.underline.bold]#What's next?# Now that milestone 2 is completed, I can focus on *milestone 3*. link:https://github.com/refinedmods/refinedstorage2/milestone/3[Milestone 3 brings more networking and wireless access tools.] After that, the last milestone, link:https://github.com/refinedmods/refinedstorage2/milestone/4[milestone 4] is on the horizon, which will bring autocrafting. [.underline.bold]#Want to try out Refined Storage 2 yourself?# * link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.2.14[Find the latest version for milestone 2 here.] * link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.] * link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!] ================================================ FILE: docs/pages/news/20240319-refined-storage-2-status-update-march.adoc ================================================ = Refined Storage 2 status update - March 2024 :type: article :description: A status update on the development of Refined Storage 2. :date: 2024-03-19 I'm starting a regular series of Refined Storage 2 status updates. link:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[If you don't know what Refined Storage 2 is, please read the FAQ first.] As you might know, Refined Storage 2 development is very intensive: * Refined Storage is being completely rewritten; * Support for the Fabric modloader is being added; * Every feature that is re-added is thought out again and changes are being made at every step of the way; * Next to being a rewrite, Refined Storage 2 also contains a bunch of new features! *... and while all this work is in progress, Refined Storage 1.x still needs maintenance and regular Minecraft ports!* [.underline.bold]#What has been going on with Refined Storage 2 since milestone 2?# Refined Storage 2 is now in the final stages of milestone 3: * The mod got ported to Minecraft 1.20.4 and the NeoForge modloader. * Support for Forge has been dropped. * The Portable Grid has been added. * Custom disk models have been added. * Fluid disks have a different in-world model now. * The Configuration Card has been added. * A new item, copies configuration to other devices. * Network Receiver / Network Transmitter / Network Card has been added. * The Storage Monitor has been added. * Wireless Grid / Wireless Transmitter / Range Upgrade has been added. * Creative Range Upgrade has been added: infinite range upgrade (not craftable). * Curios and Trinkets integration for the wireless items. * "Void excess" mode on the storages has been added. * An old, loved, removed feature from Refined Storage 1.x, now re-added for Refined Storage 2. * 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! * 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]. * Code quality improvements: * Test hardening (increasing mutation test coverage) * SonarQube fixes * Major refactoring to the storage API: * Simplifying and improving the API * Mixed storages are now possible (for example: a single disk that stores both items and fluids) [.underline.bold]#What is planned in the coming weeks?# * link:https://github.com/orgs/refinedmods/projects/6/views/8[Milestone 3 is in the process of being completed.] * The Security Card and Security Manager are being implemented. * Other remaining features to be implemented are: * Disk Manipulator * Relay * Covers [.underline.bold]#Want to try out Refined Storage 2 yourself?# * link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.3.4[Find the latest version for milestone 3 here.] * link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.] * link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!] ================================================ FILE: docs/pages/news/20240628-refined-storage-2-milestone-3-completed.adoc ================================================ = Refined Storage 2 - milestone 3 completed! :type: article :description: Milestone 3 for Refined Storage 2 has been completed. :date: 2024-06-28 image::../../assets/news/20240628-refined-storage-2-milestone-3-completed-header.png[Screenshot showing some in-game features that were finished for milestone 3] Today, *milestone 3* for Refined Storage 2 has been completed! image::../../assets/news/20240628-refined-storage-2-milestone-3-completed.png[Screenshot showing how milestone 3 is completed on GitHub] link:https://github.com/refinedmods/refinedstorage2/wiki/FAQ[If you don't know what Refined Storage 2 is, please read the FAQ first.] *Milestone 3 brings a lot of new features:* * The mod got ported to Minecraft 1.20.4 and the NeoForge modloader. ** Support for Forge has been dropped. * 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. * 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. * link:https://github.com/refinedmods/refinedstorage-emi-integration[EMI] integration has been added. * The Relay has been added with support for subnetworks. ** Watch a video about subnetworking in Refined Storage 2 link:https://www.youtube.com/watch?v=fRGH4ZUAnhQ[here]. * "Void excess" mode on the storages has been added. ** An old, loved, removed feature from Refined Storage 1.x, now re-added for Refined Storage 2. * The Portable Grid has been added. ** Custom disk models have been added. ** Fluid disks have a different in-world model now. * The Configuration Card has been added. ** A new item, copies configuration to other devices. * Network Receiver / Network Transmitter / Network Card has been added. * The Storage Monitor has been added. * Wireless Grid / Wireless Transmitter / Range Upgrade has been added. ** Creative Range Upgrade has been added: infinite range upgrade (not craftable) * The Security Card and Security Manager has been added. ** The security system has been slightly reworked and a Fallback Security Card has been added. * The Disk Interface (formerly known as "Disk Manipulator") has been added. * 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! * 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]. Some statistics: * 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)_ * Milestone 3 had 39 closed issues _(milestone 2 had 63 closed issues)_ * Milestone 3 had 15 releases _(milestone 2 had 15 releases too)_ *What's next?* link:https://github.com/refinedmods/refinedstorage2/milestone/3?closed=1[Now that milestone 3 is completed], I can focus on the last milestone, *milestone 4*! link:https://github.com/refinedmods/refinedstorage2/milestone/4[Milestone 4 brings support for Minecraft 1.21, autocrafting and Mekanism chemical integration.] After that, Refined Storage 2 will be ready and will replace Refined Storage 1. *Want to try out Refined Storage 2 yourself?* * link:https://github.com/refinedmods/refinedstorage2/releases/tag/v2.0.0-milestone.3.14[Find the latest version for milestone 3 here.] * link:https://github.com/refinedmods/refinedstorage2/wiki/Getting-started[Find the getting started guide here.] * link:https://discordapp.com/invite/VYzsydb[Join our Discord and let me know what your findings are!] ================================================ FILE: docs/pages/news/index.adoc ================================================ = News ================================================ FILE: docs/pages/news/index.html ================================================ ================================================ FILE: docs/pages/opencomputers-api.adoc ================================================ = OpenComputers API [cols="1,1"] |=== |Method|Description| |`isConnected():boolean`|Whether the node is connected. |`getEnergyUsage():number`|Gets the energy usage of this network.| |`getTasks():table`|Gets the crafting tasks of this network. |`getPattern(stack:table):table`|Get one pattern of this network. |`getFluidPattern(stack:table):table`|Get one fluid pattern of this network. |`getPatterns():table`|Gets the patterns of this network. |`getFluidPatterns():table`|Gets the fluid patterns of this network. |`hasPattern(stack:table):boolean`|Whether a crafting pattern exists for this item. |`hasFluidPattern(stack:table):boolean`|Whether a crafting pattern exists for this fluid. |`scheduleTask(stack:table[,count: number[, canSchedule: boolean]]):table`|Schedules a crafting task. |`scheduleFluidTask(stack:table[,count: number[, canSchedule: boolean]]):table`|Schedules a fluid crafting task. |`cancelTask(stack:table):number`|Cancels a task and returns the amount of tasks cancelled. |`cancelFluidTask(stack:table):number`|Cancels a fluid task and returns the amount of tasks cancelled. |`extractFluid(stack:table[,amount:number[, direction:number]]):table`|Extracts a fluid from the network. |`getFluid(stack:table):table`|Gets a fluid from the network. |`getFluids():table`|Gets a list of all fluids in this network. |`extractItem(stack:table[,count:number[, direction:number]]):table`|Extracts an item from the network. |`getItem(stack:table[,compareMeta:boolean[, compareNBT:boolean]]):table`|Gets an item from the network. |`getItems():table`|Gets a list of all items in this network. |`getStorages():table`|Gets a list of all connected storage disks and blocks in this network. |=== ================================================ FILE: docs/pages/release-notes.adoc ================================================ = Release notes ================================================ FILE: docs/pages/release-notes.html ================================================ ================================================ FILE: docs/pages/security/index.adoc ================================================ = Security - xref:security-manager.adoc[] - xref:security-card.adoc[] ================================================ FILE: docs/pages/security/security-card.adoc ================================================ = Security Card :from: v1.4.0-beta :icon: security-card.png The {doctitle} is an item that is bound to a player by right clicking. The {doctitle} has to be inserted into a xref:security-manager.adoc[], and can be configured from there as well. ================================================ FILE: docs/pages/security/security-manager.adoc ================================================ = Security Manager :from: v1.4.0-beta :icon: security-manager.png The {doctitle} is a block that can store xref:security-card.adoc[security cards]. From its GUI, you can configure what permissions each player (that is bound with a xref:security-card.adoc[]) has. Once the xref:security-card.adoc[] is inserted in the top slots, the permissions for that player will be restricted to the ones configured. == Behavior When no xref:security-card.adoc[security cards] are active on the network, everyone has access to all permissions. Start inserting xref:security-card.adoc[security cards] to define permissions for players. Players who have no configured xref:security-card.adoc[] are still able to do everything in the network (all permissions). To 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}. Operators (OPs) on a server have access to all permissions, overriding all network security. == The placer The placer of the {doctitle} will always be able to open it's GUI and change the security settings, regardless of permissions. == Permissions [cols="1,1"] |=== |Type|Description |Insert|Inserting items to the network |Extract|Extracting items from the network |Autocrafting|Starting, cancelling and viewing crafting tasks |Modify|Opening block GUIs from the network |Build|Adding or removing devices to or from the network |Security|Ability to change security options |=== include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/storage/1024k-fluid-storage-block.adoc ================================================ = 1024k Fluid Storage Block :icon: 1024k-fluid-storage-block.png :from: v0.9.0-beta include::../../partials/fluid-storage-block.adoc[] == Storage capacity The {doctitle} can store 1024.000 millibuckets or 1024 buckets of any fluid. ================================================ FILE: docs/pages/storage/1024k-fluid-storage-disk.adoc ================================================ = 1024k Fluid Storage Disk :icon: 1024k-fluid-storage-disk.png :from: v0.9.0-beta include::../../partials/fluid-storage-disk.adoc[] == Storage capacity The {doctitle} can store 1024.000 millibuckets or 1024 buckets of any fluid. ================================================ FILE: docs/pages/storage/1024k-fluid-storage-part.adoc ================================================ = 1024k Fluid Storage Part :icon: 1024k-fluid-storage-part.png :from: v0.9.0-beta The {doctitle} is used to craft the xref:1024k-fluid-storage-disk.adoc[] and xref:1024k-fluid-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/16k-storage-block.adoc ================================================ = 16k Storage Block :icon: 16k-storage-block.png :from: v0.3.0-alpha include::../../partials/storage-block.adoc[] == Storage capacity The {doctitle} can store 16.000 items. ================================================ FILE: docs/pages/storage/16k-storage-disk.adoc ================================================ = 16k Storage Disk :icon: 16k-storage-disk.png :from: v0.3.0-alpha include::../../partials/storage-disk.adoc[] == Storage capacity The {doctitle} can store 16.000 items. ================================================ FILE: docs/pages/storage/16k-storage-part.adoc ================================================ = 16k Storage Part :icon: 16k-storage-part.png :from: v0.3.0-alpha The {doctitle} is used to craft the xref:16k-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/1k-storage-block.adoc ================================================ = 1k Storage Block :icon: 1k-storage-block.png :from: v0.3.0-alpha include::../../partials/storage-block.adoc[] == Storage capacity The {doctitle} can store 1.000 items. ================================================ FILE: docs/pages/storage/1k-storage-disk.adoc ================================================ = 1k Storage Disk :icon: 1k-storage-disk.png :from: v0.3.0-alpha include::../../partials/storage-disk.adoc[] == Storage capacity The {doctitle} can store 1.000 items. ================================================ FILE: docs/pages/storage/1k-storage-part.adoc ================================================ = 1k Storage Part :icon: 1k-storage-part.png :from: v0.3.0-alpha The {doctitle} is used to craft the xref:1k-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/256k-fluid-storage-block.adoc ================================================ = 256k Fluid Storage Block :icon: 256k-fluid-storage-block.png :from: v0.9.0-beta include::../../partials/fluid-storage-block.adoc[] == Storage capacity The {doctitle} can store 256.000 millibuckets or 256 buckets of any fluid. ================================================ FILE: docs/pages/storage/256k-fluid-storage-disk.adoc ================================================ = 256k Fluid Storage Disk :icon: 256k-fluid-storage-disk.png :from: v0.9.0-beta include::../../partials/fluid-storage-disk.adoc[] == Storage capacity The {doctitle} can store 256.000 millibuckets or 256 buckets of any fluid. ================================================ FILE: docs/pages/storage/256k-fluid-storage-part.adoc ================================================ = 256k Fluid Storage Part :icon: 256k-fluid-storage-part.png :from: v0.9.0-beta The {doctitle} is used to craft the xref:256k-fluid-storage-disk.adoc[] and xref:256k-fluid-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/4096k-fluid-storage-block.adoc ================================================ = 4096k Fluid Storage Block :icon: 4096k-fluid-storage-block.png :from: v0.9.0-beta include::../../partials/fluid-storage-block.adoc[] == Storage capacity The {doctitle} can store 4096.000 millibuckets or 4096 buckets of any fluid. ================================================ FILE: docs/pages/storage/4096k-fluid-storage-disk.adoc ================================================ = 4096k Fluid Storage Disk :icon: 4096k-fluid-storage-disk.png :from: v0.9.0-beta include::../../partials/fluid-storage-disk.adoc[] == Storage capacity The {doctitle} can store 4096.000 millibuckets or 4096 buckets of any fluid. ================================================ FILE: docs/pages/storage/4096k-fluid-storage-part.adoc ================================================ = 4096k Fluid Storage Part :icon: 4096k-fluid-storage-part.png :from: v0.9.0-beta The {doctitle} is used to craft the xref:4096k-fluid-storage-disk.adoc[] and xref:4096k-fluid-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/4k-storage-block.adoc ================================================ = 4k Storage Block :icon: 4k-storage-block.png :from: v0.3.0-alpha include::../../partials/storage-block.adoc[] == Storage capacity The {doctitle} can store 4.000 items. ================================================ FILE: docs/pages/storage/4k-storage-disk.adoc ================================================ = 4k Storage Disk :icon: 4k-storage-disk.png :from: v0.3.0-alpha include::../../partials/storage-disk.adoc[] == Storage capacity The {doctitle} can store 4.000 items. ================================================ FILE: docs/pages/storage/4k-storage-part.adoc ================================================ = 4k Storage Part :icon: 4k-storage-part.png :from: v0.3.0-alpha The {doctitle} is used to craft the xref:4k-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/64k-fluid-storage-block.adoc ================================================ = 64k Fluid Storage Block :icon: 64k-storage-block.png :from: v0.9.0-beta include::../../partials/fluid-storage-block.adoc[] == Storage capacity The {doctitle} can store 64.000 millibuckets or 64 buckets of any fluid. ================================================ FILE: docs/pages/storage/64k-fluid-storage-disk.adoc ================================================ = 64k Fluid Storage Disk :icon: 64k-fluid-storage-disk.png :from: v0.9.0-beta include::../../partials/fluid-storage-disk.adoc[] == Storage capacity The {doctitle} can store 64.000 millibuckets or 64 buckets of any fluid. ================================================ FILE: docs/pages/storage/64k-fluid-storage-part.adoc ================================================ = 64k Fluid Storage Part :icon: 64k-fluid-storage-part.png :from: v0.9.0-beta The {doctitle} is used to craft the xref:64k-fluid-storage-disk.adoc[] and xref:64k-fluid-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/64k-storage-block.adoc ================================================ = 64k Storage Block :icon: 64k-storage-block.png :from: v0.3.0-alpha include::../../partials/storage-block.adoc[] == Storage capacity The {doctitle} can store 64.000 items. ================================================ FILE: docs/pages/storage/64k-storage-disk.adoc ================================================ = 64k Storage Disk :icon: 64k-storage-disk.png :from: v0.3.0-alpha include::../../partials/storage-disk.adoc[] == Storage capacity The {doctitle} can store 64.000 items. ================================================ FILE: docs/pages/storage/64k-storage-part.adoc ================================================ = 64k Storage Part :icon: 64k-storage-part.png :from: v0.3.0-alpha The {doctitle} is used to craft the xref:64k-storage-block.adoc[]. ================================================ FILE: docs/pages/storage/creative-fluid-storage-block.adoc ================================================ = Creative Fluid Storage Block :icon: creative-fluid-storage-block.png :from: v0.9.0-beta include::../../partials/fluid-storage-block.adoc[] == Storage capacity The {doctitle} can store an infinite amount of buckets. It can only be obtained in creative mode. ================================================ FILE: docs/pages/storage/creative-fluid-storage-disk.adoc ================================================ = Creative Fluid Storage Disk :icon: creative-fluid-storage-disk.png :from: v0.9.0-beta include::../../partials/fluid-storage-disk.adoc[] == Storage capacity The {doctitle} can store an infinite amount of buckets. It can only be obtained in creative mode. ================================================ FILE: docs/pages/storage/creative-storage-block.adoc ================================================ = Creative Storage Block :icon: creative-storage-block.png :from: v0.3.0-alpha include::../../partials/storage-block.adoc[] == Storage capacity The {doctitle} can store an infinite amount of items. It can only be obtained in creative mode. ================================================ FILE: docs/pages/storage/creative-storage-disk.adoc ================================================ = Creative Storage Disk :icon: creative-storage-disk.png :from: v0.3.0-alpha include::../../partials/storage-disk.adoc[] == Storage capacity The {doctitle} can store an infinite amount of items. It can only be obtained in creative mode. ================================================ FILE: docs/pages/storage/disk-drive.adoc ================================================ = Disk Drive :icon: disk-drive.png :from: v0.3.0-alpha The 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]. == Priority A (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in). == Whitelist and blacklist There 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. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Mode The Disk Drive has support for the following modes: - Insert and extract (default) - Insert only - Extract only ================================================ FILE: docs/pages/storage/external-storage.adoc ================================================ = External Storage :from: v0.3.0-alpha :icon: external-storage.png The {doctitle} is a block that provides the storage network with storage of the inventory or fluid tank in front of the device. == Priority A (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in). == Whitelist and blacklist There is also a whitelist and blacklist option to only allow or forbid some items or fluids from entering the connected inventory. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Mode The {doctitle} has support for the following modes: - Insert and extract (default) - Insert only - Extract only ================================================ FILE: docs/pages/storage/index.adoc ================================================ = Storage - xref:storing-externally.adoc[] - xref:storing-fluids.adoc[] == Network devices - xref:disk-drive.adoc[] - xref:external-storage.adoc[] [#_storage_parts] == Storage parts - xref:1k-storage-part.adoc[] - xref:4k-storage-part.adoc[] - xref:16k-storage-part.adoc[] - xref:64k-storage-part.adoc[] [#_storage_disks] == Storage disks - xref:1k-storage-disk.adoc[] - xref:4k-storage-disk.adoc[] - xref:16k-storage-disk.adoc[] - xref:64k-storage-disk.adoc[] - xref:creative-storage-disk.adoc[] [#_storage_blocks] == Storage blocks - xref:1k-storage-block.adoc[] - xref:4k-storage-block.adoc[] - xref:16k-storage-block.adoc[] - xref:64k-storage-block.adoc[] - xref:creative-storage-block.adoc[] [#_fluid_storage_parts] == Fluid storage parts - xref:64k-fluid-storage-part.adoc[] - xref:256k-fluid-storage-part.adoc[] - xref:1024k-fluid-storage-part.adoc[] - xref:4096k-fluid-storage-part.adoc[] [#_fluid_storage_disks] == Fluid storage disks - xref:64k-fluid-storage-disk.adoc[] - xref:256k-fluid-storage-disk.adoc[] - xref:1024k-fluid-storage-disk.adoc[] - xref:4096k-fluid-storage-disk.adoc[] - xref:creative-fluid-storage-disk.adoc[] [#_fluid_storage_blocks] == Fluid storage blocks - xref:64k-fluid-storage-block.adoc[] - xref:256k-fluid-storage-block.adoc[] - xref:1024k-fluid-storage-block.adoc[] - xref:4096k-fluid-storage-block.adoc[] - xref:creative-fluid-storage-block.adoc[] ================================================ FILE: docs/pages/storage/storage-housing.adoc ================================================ = Storage Housing :icon: storage-housing.png :from: v0.6.0-alpha A 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. The 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. ================================================ FILE: docs/pages/storage/storing-externally.adoc ================================================ = Storing externally So far you've used xref:index.adoc#_storage_disks[storage disks] or xref:index.adoc#_storage_blocks[storage blocks]. What if you want to use a chest or another inventory as storage? == The External Storage Craft an xref:external-storage.adoc[] and connect it to an external inventory like a link:https://minecraft.gamepedia.com/Chest[Chest]. If you now insert items, they will go in the inventory. You can also filter items that can enter the external inventory with the filter slots. == Supported storages The xref:external-storage.adoc[] supports every block that is an inventory. Some examples: - link:https://minecraft.gamepedia.com/Chest[Chests] - Storage Drawers - Regular drawers - Drawer Controller - Iron Chests - etc... == Using an External Storage alongside other storages When you insert or extract an item from the storage network, Refined Storage will extract or insert from the storage with the highest priority first. Simply give a storage a higher priority than the other one, and Refined Storage will prioritize correctly. If the storage is full, Refined Storage will attempt to insert or extract from the next available storage, with a lower priority. ================================================ FILE: docs/pages/storage/storing-fluids.adoc ================================================ = Storing fluids As opposed to only item storage, Refined Storage is able to store fluids as well. This is done in the entirely same way as item storages. All 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. == Storage The same way as you connect item storages, you can connect fluid storages as well: - xref:index.adoc#_fluid_storage_disks[Any fluid storage disk] in a xref:disk-drive.adoc[] - xref:index.adoc#_fluid_storage_blocks[Any fluid storage block] - xref:external-storage.adoc[] in fluid mode == Accessing fluids Use a xref:../viewing-resources/fluid-grid.adoc[]. == Manipulating fluids Any block that would manipulate items can manipulate fluids as well by simply putting the block in fluid mode. There is one exception to this: the xref:../input-and-output/interface.adoc[] has no fluid mode. Use a xref:../input-and-output/fluid-interface.adoc[] instead. ================================================ FILE: docs/pages/upgrades/crafting-upgrade.adoc ================================================ = Crafting Upgrade :icon: crafting-upgrade.png :from: v0.6.0-alpha The {doctitle} will schedule a crafting task when the item being used in a device is needed but not available. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/fortune-upgrade.adoc ================================================ = Fortune Upgrade :icon: fortune-upgrade.png :from: v1.2.0 The {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. This upgrade has 3 versions: - Fortune 1 - Fortune 2 - Fortune 3 By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/index.adoc ================================================ = Upgrades - xref:upgrade.adoc[] - xref:range-upgrade.adoc[] - xref:speed-upgrade.adoc[] - xref:stack-upgrade.adoc[] - xref:crafting-upgrade.adoc[] - xref:regulator-upgrade.adoc[] - xref:fortune-upgrade.adoc[] - xref:silk-touch-upgrade.adoc[] - xref:interdimensional-upgrade.adoc[] ================================================ FILE: docs/pages/upgrades/interdimensional-upgrade.adoc ================================================ = Interdimensional Upgrade :icon: interdimensional-upgrade.png :from: v0.8.14-beta :to: v1.6.10 [.alert.alert-warning] **** This upgrade has been removed in v1.6.10. The xref:../wireless-networking/network-transmitter.adoc[] is now cross dimensional by default. **** The Interdimensional Upgrade is an upgrade that allows the xref:../wireless-networking/network-transmitter.adoc[] to work cross-dimensionally. This upgrade takes a lot of extra FE/t by default (1000 FE/t extra). ================================================ FILE: docs/pages/upgrades/range-upgrade.adoc ================================================ = Range Upgrade :icon: range-upgrade.png :from: v0.6.0-alpha The {doctitle} increases the range of the xref:../wireless-networking/wireless-transmitter.adoc[]. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/regulator-upgrade.adoc ================================================ = Regulator Upgrade :icon: regulator-upgrade.png :from: v1.8.3-beta The 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. It will try to keep the connected inventory stocked by using items or fluids from the storage network. As 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. Additionally, 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. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/silk-touch-upgrade.adoc ================================================ = Silk Touch Upgrade :icon: silk-touch-upgrade.png :from: v1.2.0 The {doctitle} makes the xref:../input-and-output/destructor.adoc[] use Silk Touch on the blocks that it is breaking. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/speed-upgrade.adoc ================================================ = Speed Upgrade :icon: speed-upgrade.png :from: v0.6.0-alpha The {doctitle} will increase the speed of the device that it is being inserted to. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/stack-upgrade.adoc ================================================ = Stack Upgrade :icon: stack-upgrade.png :from: v0.7.7-beta The {doctitle} will improve item or fluid transfer speeds by using a whole stack (64 items) instead of 1 item at a time. It can be combined with xref:speed-upgrade.adoc[speed upgrades] to let the device go to the next slot quicker. By using this upgrade, the amount of FE/t that this device draws will increase. ================================================ FILE: docs/pages/upgrades/upgrade.adoc ================================================ = Upgrade :icon: upgrade.png :from: v0.6.0-alpha The {doctitle} is the base item used for xref:index.adoc[every type of upgrade]. ================================================ FILE: docs/pages/utility/advanced-processor.adoc ================================================ = Advanced Processor :icon: advanced-processor.png :from: v0.3.0-alpha include::../../partials/processor.adoc[] ================================================ FILE: docs/pages/utility/basic-processor.adoc ================================================ = Basic Processor :icon: basic-processor.png :from: v0.3.0-alpha include::../../partials/processor.adoc[] ================================================ FILE: docs/pages/utility/block-of-quartz-enriched-iron.adoc ================================================ = Block of Quartz Enriched Iron :from: v1.4.0-beta :icon: block-of-quartz-enriched-iron.png The {doctitle} is xref:quartz-enriched-iron.adoc[] in block form. ================================================ FILE: docs/pages/utility/construction-core.adoc ================================================ = Construction Core :from: v0.3.0-alpha :icon: construction-core.png The {doctitle} is used in recipes for devices that turn resources from the storage network into resources in the world. ================================================ FILE: docs/pages/utility/cover.adoc ================================================ = Cover :icon: cover.png :from: v1.6.0-alpha A {doctitle} is an item used to hide xref:../networking/cable.adoc[cables]. You 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[]. It will block network connections, xref:../networking/cable.adoc[cables] can't pass through the "hidden" side. They can be removed by sneaking and right-clicking them with the xref:wrench.adoc[]. ================================================ FILE: docs/pages/utility/cut-silicon.adoc ================================================ = Cut Silicon :icon: cut-silicon.png :from: v0.3.0-alpha :to: v1.6.6 [.alert.alert-warning] **** {doctitle} has been removed in v1.6.6. It has been replaced with xref:processor-binding.adoc[]. **** {doctitle} is used to craft the various processors. It is made with a xref:cutting-tool.adoc[]. ================================================ FILE: docs/pages/utility/cutting-tool.adoc ================================================ = Cutting Tool :icon: cutting-tool.png :from: v1.6.0 :to: v1.7.0-alpha [.alert.alert-warning] **** The Cutting Tool has been removed in v1.7.0-alpha. Crafting covers now uses an iron nugget instead. **** The Cutting Tool is a tool that is used to craft xref:../utility/cover.adoc[covers]. ================================================ FILE: docs/pages/utility/destruction-core.adoc ================================================ = Destruction Core :from: v0.3.0-alpha :icon: destruction-core.png The {doctitle} is used in recipes for devices that turn resources from the world into resources in the storage network. ================================================ FILE: docs/pages/utility/filter.adoc ================================================ = Filter :icon: filter.png :from: v0.8.13-beta The {doctitle} is an item that can be used in any xref:../viewing-resources/grid.adoc[]. In 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. == Items and fluids The 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. == {doctitle}ing The player can choose to let the filter be damage or damage sensitive. It is also possible to use a mod filter. The {doctitle} can be set in a whitelist or blacklist mode, too. == Icon and name The player can also configure an icon and name for the {doctitle}. In item and fluid mode an icon can be specified. As soon as the {doctitle} has an icon specified, it will appear as a tab in the xref:../viewing-resources/grid.adoc[]. Then, open the tab to see the filtered items or fluids. == Clearing Use SHIFT + right click in your inventory while holding the {doctitle} to clear it. ================================================ FILE: docs/pages/utility/hollow-cover.adoc ================================================ = Hollow Cover :icon: hollow-cover.png :from: v1.6.0 A {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. You 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. It will let a network signal through. They can be removed by sneaking and right-clicking them with the xref:wrench.adoc[]. ================================================ FILE: docs/pages/utility/improved-processor.adoc ================================================ = Improved Processor :icon: improved-processor.png :from: v0.3.0-alpha include::../../partials/processor.adoc[] ================================================ FILE: docs/pages/utility/index.adoc ================================================ = Utility - xref:quartz-enriched-iron.adoc[] - xref:block-of-quartz-enriched-iron.adoc[] - xref:silicon.adoc[] - xref:cut-silicon.adoc[] - xref:wrench.adoc[] - xref:cutting-tool.adoc[] - xref:filter.adoc[] - xref:machine-casing.adoc[] - xref:solderer.adoc[] == Raw Processors - xref:processor-binding.adoc[] - xref:raw-basic-processor.adoc[] - xref:raw-improved-processor.adoc[] - xref:raw-advanced-processor.adoc[] == Processors - xref:basic-processor.adoc[] - xref:improved-processor.adoc[] - xref:advanced-processor.adoc[] == Cores - xref:construction-core.adoc[] - xref:destruction-core.adoc[] == Covers - xref:cover.adoc[] - xref:hollow-cover.adoc[] ================================================ FILE: docs/pages/utility/machine-casing.adoc ================================================ = Machine Casing :icon: machine-casing.png :from: v0.3.0-alpha The {doctitle} is a block that is used to craft the various Refined Storage devices. ================================================ FILE: docs/pages/utility/processor-binding.adoc ================================================ = Processor Binding :icon: processor-binding.png :from: v1.6.6 {doctitle} is used to craft the various processors. ================================================ FILE: docs/pages/utility/quartz-enriched-iron.adoc ================================================ = Quartz Enriched Iron :icon: quartz-enriched-iron.png :from: v0.3.0-alpha {doctitle} is like the name says, iron enriched with quartz. It is used in almost all the recipes in Refined Storage. ================================================ FILE: docs/pages/utility/raw-advanced-processor.adoc ================================================ = Raw Advanced Processor :icon: raw-advanced-processor.png :from: v0.3.0-alpha The {doctitle} is used to craft a xref:advanced-processor.adoc[]. ================================================ FILE: docs/pages/utility/raw-basic-processor.adoc ================================================ = Raw Basic Processor :icon: raw-basic-processor.png :from: v0.3.0-alpha The {doctitle} is used to craft a xref:basic-processor.adoc[]. ================================================ FILE: docs/pages/utility/raw-improved-processor.adoc ================================================ = Raw Improved Processor :icon: raw-improved-processor.png :from: v0.3.0-alpha The {doctitle} is used to craft a xref:improved-processor.adoc[]. ================================================ FILE: docs/pages/utility/silicon.adoc ================================================ = Silicon :icon: silicon.png :since: v0.3.0-alpha {doctitle} can be obtained by smelting quartz. This item has no use other than being used in crafting recipes. ================================================ FILE: docs/pages/utility/solderer.adoc ================================================ = Solderer :icon: solderer.png :from: v0.3.0-alpha :to: v1.6.0 [.alert.alert-warning] **** The {doctitle} has been removed in v1.6.0. It has been replaced with xref:processor-binding.adoc[]. **** The {doctitle} is a device that is used to craft several items and blocks. The {doctitle} is not sided. You can insert from any side and it'll automatically put the items in the right slot. Use of link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] is (highly) recommended to see the recipes of the {doctitle}. == Applicable upgrades - xref:../upgrades/speed-upgrade.adoc[] ================================================ FILE: docs/pages/utility/wrench.adoc ================================================ = Wrench :icon: wrench.png :from: v1.2.0 The {doctitle} is a tool that can do two things: - Rotate blocks - Break Refined Storage xref:cover.adoc[covers] Simply sneak and right click when using the {doctitle}. ================================================ FILE: docs/pages/viewing-resources/crafting-grid.adoc ================================================ = Crafting Grid :icon: crafting-grid.png :from: v0.3.0-alpha The {doctitle} is the same as a regular xref:grid.adoc[], but has a crafting inventory. When 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. == Recipe transferring The {doctitle} integrates with link:https://minecraft.curseforge.com/projects/jei[JEI (Just Enough Items)] so the player can use recipe transferring. Refined Storage will warn you when you don't have the required item present in your inventory, storage network or crafting matrix. Even with this warning, you can still transfer items. If 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. Note that you need a xref:../autocrafting/pattern.adoc[] configured for these items. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/viewing-resources/fluid-grid.adoc ================================================ = Fluid Grid :from: v0.9.0-beta :icon: fluid-grid.png The {doctitle} is the same as a regular xref:grid.adoc[], but is used for viewing fluids in the fluid storage of your storage network. == Inserting To insert a fluid, players can shift click on a fluid container like a bucket in their player inventory while in the {doctitle} GUI. The player can also click the fluid container in the GUI to insert it. == Extracting Players can extract the fluid by clicking on it. The {doctitle} will then fill a bucket with the selected fluid. Refined Storage will first search an empty bucket in your inventory. If none is found, a bucket will be searched in your storage network. Some 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[]. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/viewing-resources/grid.adoc ================================================ = Grid :icon: grid.png :from: v0.3.0-alpha The {doctitle} is a block that allows access to the items and fluids in the storage network. The player can extract items or fluids from the central GUI. [#_controls] == Controls [cols="1,1"] |=== | Type | Description | Left click | Takes at most 64 items | Right click | Takes at most 32 items | Middle click | Takes 1 item (removed since v1.9.7) | SHIFT + Mouse scroll in the player inventory | Pushes 1 item to or from the player's inventory (since v1.9.7) | SHIFT + Mouse scroll in the {doctitle} inventory | Pushes 1 item to or from the {doctitle} inventory (since v1.9.7) | CTRL + Mouse scroll | Pushes 1 item to or from the player's mouse (since v1.9.7) | SHIFT | Pushes the items to the player's inventory | SHIFT + CTRL | Forces the crafting window to open *even if the item or fluid is available* | CTRL + X | Clears crafting matrix | Right click on search bar | Clears the search query | Tab | Selects the search bar when the {doctitle} isn't in autoselection mode | When in the crafting start GUI, pressing SHIFT | Skips the crafting preview window |=== == Sorting The items or fluids in a {doctitle} can be sorted in various ways: - By name - By quantity - By item ID - Last modified - InventoryTweaks sorting (only available if InventoryTweaks is installed) The sorting direction can also be chosen (ascending or descending). include::../../partials/search-box.adoc[] == Filter In 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}. == Tabs A {doctitle} can also have tabs. When clicking on the tab, only items configured in the xref:../utility/filter.adoc[] are visible. To use tabs in the {doctitle}, make a xref:../utility/filter.adoc[] with an icon specified. To have more than 4 tabs, put a xref:../utility/filter.adoc[] in a xref:../utility/filter.adoc[]. == Sizes The size of any {doctitle} can be configured as well: - Stretched (default) - Small - Medium - Large When choosing the stretched size, the {doctitle} will take up all the vertical screen space. This can be limited through the `maxRowsStretch` config option. == Display The {doctitle} can be configured to only show craftable items or only non-craftable items. By default, the tooltips for items in a {doctitle} are a little bit bigger to display the total item count and the last modified information. This can be turned off by using the `detailedTooltip` config option. By default, the {doctitle} uses a small font size to display item or fluid quantities. Use the `largeFont` config option to change this. == Remember search query The {doctitle} can be configured to remember the search query when closing and re-opening the GUI. You can do this by modifying the `rememberSearchQuery` config option. == Prevent sorting while shift is down By default, the {doctitle} doesn't perform sorting when you're shift clicking items out of the storage network. This is done to prevent items and fluids shifting around your screen. As soon as you stop pressing the shift key, the view is sorted again. To disable this behavior, modify the `preventSortingWhileShiftIsDown` config option. include::../../partials/recoloring.adoc[] ================================================ FILE: docs/pages/viewing-resources/how-to-view-resources.adoc ================================================ = How to view resources == Grid You can use the xref:grid.adoc[], xref:crafting-grid.adoc[] or xref:fluid-grid.adoc[] to view resources in your network. [#_wireless_access] == Wireless access Refined Storage has extensive wireless abilities to access your storage network remotely. Craft a xref:../wireless-networking/wireless-grid.adoc[] and right click it on a xref:../networking/controller.adoc[]. Craft a xref:../wireless-networking/wireless-transmitter.adoc[] and add it to your network. You can now access your storage in a radius around the xref:../wireless-networking/wireless-transmitter.adoc[]. Want a higher range? Simply place multiple xref:../wireless-networking/wireless-transmitter.adoc[wireless transmitters] around your world, but not next to each other. == Portable Grid Want to access an individual xref:../storage/index.adoc#_storage_disks[storage disk]? Use a xref:portable-grid.adoc[]. Give it energy and insert a disk, and you're good to go. It doesn't depend on a storage network. == Storage Monitor Want to see how much you have of an item in your storage network? Connect a xref:storage-monitor.adoc[] and configure an item to display. You can then see how much you have of that item and interact with it by inserting or extracting multiple items at once. ================================================ FILE: docs/pages/viewing-resources/index.adoc ================================================ = Viewing resources - xref:how-to-view-resources.adoc[] - xref:grid.adoc[] - xref:crafting-grid.adoc[] - xref:fluid-grid.adoc[] - xref:storage-monitor.adoc[] - xref:portable-grid.adoc[] ================================================ FILE: docs/pages/viewing-resources/portable-grid.adoc ================================================ = Portable Grid :icon: portable-grid.png :from: v1.4.5-beta The {doctitle} is a portable storage that isn't connected to a network. It allows you to interact with a xref:../storage/index.adoc#_storage_disks[storage disk] while not being connected to a network. As 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. It's essentially a xref:../storage/disk-drive.adoc[] and xref:grid.adoc[] in one block or item. It can be placed in the world, or, be used as a handheld device as well. To place it in the world hold the {doctitle} while sneaking. == Energy behavior To use the {doctitle} the item or block needs Forge Energy (FE). The {doctitle} draws energy on following actions: [cols="1,1"] |=== |Action|Amount of Forge Energy drawed |Opening the {doctitle}|30 FE |Extracting an item or fluid from storage|3 FE |Inserting an item or fluid to storage|3 FE |=== ================================================ FILE: docs/pages/viewing-resources/storage-monitor.adoc ================================================ = Storage Monitor :icon: storage-monitor.png :from: v1.4.1-beta The {doctitle} is a block that displays the current amount of a certain item or fluid in your storage system. == Configuration Use SHIFT + right click on the block to open a GUI to configure the item or fluid being displayed. == Item inserting and extracting - You can extract the item specified from the system by left clicking - Regular left click for a full stack (64 items) - Shift left click for 1 of a stack (1 item) - You can insert items from your inventory that match the item being displayed by right clicking - Right click quickly to insert all items matching the item displayed in your == Fluid inserting and extracting (since v1.8.1) - You can extract the fluid specified in bucket from from the system by shift left clicking - Make sure you have a bucket in your inventory or storage network - You can insert fluids from your inventory that match the fluid being displayed by right clicking - Make sure you have a fluid container in your inventory that contains the fluid you want to insert ================================================ FILE: docs/pages/wireless-networking/creative-wireless-crafting-monitor.adoc ================================================ = Creative Wireless Crafting Monitor :icon: wireless-crafting-monitor.png :from: v1.2.1 The {doctitle} is the same as a regular xref:wireless-crafting-monitor.adoc[] but has infinite energy. It can only be obtained in creative mode. ================================================ FILE: docs/pages/wireless-networking/creative-wireless-fluid-grid.adoc ================================================ = Creative Wireless Fluid Grid :from: v1.4.0-beta :icon: wireless-fluid-grid.png The {doctitle} is the same as a regular xref:wireless-fluid-grid.adoc[] but has infinite energy. It can only be obtained in creative mode. ================================================ FILE: docs/pages/wireless-networking/creative-wireless-grid.adoc ================================================ = Creative Wireless Grid :icon: wireless-grid.png :from: v0.5.3-alpha The {doctitle} is the same as a regular xref:wireless-grid.adoc[] but has infinite energy. It can only be obtained in creative mode. ================================================ FILE: docs/pages/wireless-networking/index.adoc ================================================ = Wireless networking - xref:networks-over-long-distances.adoc[] == Wireless tools - xref:wireless-transmitter.adoc[] - xref:wireless-grid.adoc[] - xref:creative-wireless-grid.adoc[] - xref:wireless-fluid-grid.adoc[] - xref:creative-wireless-fluid-grid.adoc[] - xref:wireless-crafting-monitor.adoc[] - xref:creative-wireless-crafting-monitor.adoc[] - xref:wireless-crafting-grid.adoc[] == Wireless networks - xref:network-card.adoc[] - xref:network-receiver.adoc[] - xref:network-transmitter.adoc[] ================================================ FILE: docs/pages/wireless-networking/network-card.adoc ================================================ = Network Card :from: v0.8.13-beta :icon: network-card.png A {doctitle} is an item that stores the coordinates of a xref:network-receiver.adoc[]. The player has to insert the {doctitle} in a xref:network-transmitter.adoc[]. ================================================ FILE: docs/pages/wireless-networking/network-receiver.adoc ================================================ = Network Receiver :icon: network-receiver.png :from: v0.8.13-beta The {doctitle} is the block that receives a signal from the xref:network-transmitter.adoc[]. In order for the {doctitle} to work reliably the {doctitle} has to be chunkloaded. include::../../partials/recoloring.adoc[] == Using Refined Storage v1.7.x or v1.8.x? Cross dimensional functionality isn't available in this version. ================================================ FILE: docs/pages/wireless-networking/network-transmitter.adoc ================================================ = Network Transmitter :icon: network-transmitter.png :from: v0.8.13-beta A {doctitle} sends a network signal to a xref:network-receiver.adoc[] that is specified in the given xref:network-card.adoc[]. In order for the {doctitle} to work the xref:../networking/controller.adoc[] where the {doctitle} is connected to has to be chunkloaded. The {doctitle} can work in the current dimension or across different dimensions. include::../../partials/recoloring.adoc[] == Using Refined Storage v1.7.x or v1.8.x? Cross dimensional functionality isn't available in this version. ================================================ FILE: docs/pages/wireless-networking/networks-over-long-distances.adoc ================================================ = Networks over long distances Refined Storage supports 2 scenarios for long distance networking: - xref:../viewing-resources/how-to-view-resources.adoc#_wireless_access[Viewing your resources wirelessly] - Extending a network over a long distance without using cables (see below) == The problem Sometimes, you may have different areas all scattered throughout your world. Here is the problem: you want access to your Refined Storage system on all of those areas. You could lay xref:../networking/cable.adoc[] from your base to every area, but what if said area is 1000 blocks away? Are you really going to craft 1000 xref:../networking/cable.adoc[cables]? Didn't think so. == The solution Use the xref:network-transmitter.adoc[] and xref:network-receiver.adoc[]. Simply craft a xref:network-transmitter.adoc[] and connect it to your Refined Storage system in your main base. Next up, craft a xref:network-card.adoc[]. I'll be telling what you need this for in a second, bear with me. After crafting a xref:network-card.adoc[], craft a xref:network-receiver.adoc[] and place it in the area far away from your base. If 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. Take the xref:network-card.adoc[] and right click it on the xref:network-receiver.adoc[]. Put the xref:network-card.adoc[] in the xref:network-transmitter.adoc[] so the xref:network-transmitter.adoc[] knows where to send a signal to. And now you are done. Simply connect machines to your xref:network-receiver.adoc[] according to the normal machine connecting rules. I suppose you could treat the xref:network-receiver.adoc[] as a xref:... == One very important thing to note The 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. After linking, both areas have to stay chunkloaded. == Using Refined Storage v1.7.x or v1.8.x? Cross dimensional functionality isn't available in this version. ================================================ FILE: docs/pages/wireless-networking/wireless-crafting-grid.adoc ================================================ = Wireless Crafting Grid :icon: wireless-crafting-grid.png With the {doctitle} the player can access their items and has the ability to craft using a crafting matrix from anywhere. It is not available in the base Refined Storage mod, but in Refined Storage Addons. To activate the {doctitle}, the player has to right-click the {doctitle} on a xref:../networking/controller.adoc[]. If you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device. To use the {doctitle} the item needs Forge Energy. You'll have to charge it in a block that charges items from another mod. After doing all these steps, the {doctitle} is still missing a signal from the storage network. Add at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks. If the {doctitle} is ready for use, it will light up blue. == Troubleshooting Sometimes, the {doctitle} doesn't open or stays gray. To enable it make sure that: - The {doctitle} is bound to a xref:../networking/controller.adoc[] - There is at least 1 xref:wireless-transmitter.adoc[] connected to the network - That you are in range of the xref:wireless-transmitter.adoc[] - The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to == Energy behavior The {doctitle} draws energy on following actions: [cols="1,1"] |=== |Action|Amount of Forge Energy used |Opening the {doctitle}|30 FE |Pulling an item from storage|3 FE |Pushing an item to storage|3 FE |Crafting an item|1 FE |Clearing the crafting matrix|10 FE |=== ================================================ FILE: docs/pages/wireless-networking/wireless-crafting-monitor.adoc ================================================ = Wireless Crafting Monitor :icon: wireless-crafting-monitor.png :from: v1.2.1 With the {doctitle} the player can see what is crafting from anywhere. To activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[]. If you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device. To use the {doctitle} the item needs Forge Energy. You'll have to charge it in a block that charges items from another mod. After doing all these steps, the {doctitle} is still missing a signal from the system. Add at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks. If the {doctitle} is ready for use, it will light up blue. == Troubleshooting Sometimes, the {doctitle} doesn't open or stays grey. To enable it make sure that: - The {doctitle} is bound to a xref:../networking/controller.adoc[] - There is at least 1 xref:wireless-transmitter.adoc[] connected to the network - That you are in range of the xref:wireless-transmitter.adoc[] - The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to == Energy behavior The {doctitle} draws energy on following actions: [cols="1,1"] |=== |Action|Amount of Forge Energy used |Opening the {doctitle}|35 FE |Cancelling a task|4 FE |Cancelling all tasks|5 FE |=== ================================================ FILE: docs/pages/wireless-networking/wireless-fluid-grid.adoc ================================================ = Wireless Fluid Grid :icon: wireless-fluid-grid.png :from: v1.4.0-beta With the {doctitle} the player can access their fluids from anywhere. To activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[]. If you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device. To use the {doctitle} the item needs Forge Energy. You'll have to charge it in a block that charges items from another mod. After doing all these steps, the {doctitle} is still missing a signal from the system. Add at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks. If the {doctitle} is ready for use, it will light up blue. == Troubleshooting Sometimes, the {doctitle} doesn't open or stays gray. To enable it make sure that: - The {doctitle} is bound to a xref:../networking/controller.adoc[] - There is at least 1 xref:wireless-transmitter.adoc[] connected to the network - That you are in range of the xref:wireless-transmitter.adoc[] - The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to == Energy behavior The {doctitle} draws energy on following actions: [cols="1,1"] |=== |Action|Amount of Forge Energy used |Opening the {doctitle}|30 FE |Pulling a fluid from storage|3 FE |Pushing a fluid to storage|3 FE |=== ================================================ FILE: docs/pages/wireless-networking/wireless-grid.adoc ================================================ = Wireless Grid :from: v0.3.0-alpha :icon: wireless-grid.png With the {doctitle} the player can access their items from anywhere. To activate the {doctitle}, the player has to right click the {doctitle} on a xref:../networking/controller.adoc[]. If you're playing on Refined Storage v1.7.x or higher you can bind the {doctitle} by right clicking on any connected network device. To use the {doctitle} the item needs Forge Energy (FE). You'll have to charge it in a block that charges items from another mod. After doing all these steps, the {doctitle} is still missing a signal from the storage network. Add at least 1 xref:wireless-transmitter.adoc[] to the network to get a basic range of 16 blocks. If the {doctitle} is ready for use, it will light up blue. == Troubleshooting Sometimes, the {doctitle} doesn't open or stays gray. To enable it make sure that: - The {doctitle} is bound to a xref:../networking/controller.adoc[] - There is at least 1 xref:wireless-transmitter.adoc[] connected to the network - That you are in range of the xref:wireless-transmitter.adoc[] - The xref:../networking/controller.adoc[] block is still in the world on the place where you bound it to == Energy behavior The {doctitle} draws energy on following actions: [cols="1,1"] |=== |Action|Amount of Forge Energy used |Opening the {doctitle}|30 FE |Pulling an item from storage|3 FE |Pushing an item to storage|3 FE |=== ================================================ FILE: docs/pages/wireless-networking/wireless-transmitter.adoc ================================================ = Wireless Transmitter :icon: wireless-transmitter.png :from: v0.6.0-alpha The {doctitle} is used to send signals to wireless network items in Refined Storage. == Range The default range is 16 blocks, but can be upgraded with xref:../upgrades/range-upgrade.adoc[range upgrades]. === Bigger range Keep in mind, **you are not limited to 1 {doctitle}**! You can spread multiple around in your world, each maximally upgraded with xref:../upgrades/range-upgrade.adoc[range upgrades]. Note that every {doctitle} needs to be connected to the network through a xref:../networking/cable.adoc[] or xref:network-receiver.adoc[]. == Placing transmitters efficiently Placing 2 {doctitle}s just next to each other will not do that much. The 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. Instead, you have to spread your wireless transmitters around. include::../../partials/recoloring.adoc[] == Applicable upgrades - xref:../upgrades/range-upgrade.adoc[] ================================================ FILE: docs/partials/fluid-storage-block.adoc ================================================ The {doctitle} is a block that provides the system with storage. It is similar to the xref:../pages/storage/index.adoc#_fluid_storage_disks[fluid storage disk], but can be placed in the world. When breaking the {doctitle}, the fluids that it holds persist, so you won't lose any of your fluids. The {doctitle} won't despawn when dropped in the world. == Priority A (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in). == Whitelist and blacklist There is also a whitelist and blacklist option to only allow or forbid some fluid from entering the {doctitle}. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Mode The {doctitle} has support for the following modes: - Insert and extract (default) - Insert only - Extract only == Uncrafting Sneak and right click while holding the empty {doctitle} to retrieve the various parts back: - The corresponding xref:../pages/storage/index.adoc#_fluid_storage_parts[Fluid Storage Part] - xref:../pages/utility/basic-processor.adoc[] - xref:../pages/utility/machine-casing.adoc[] ================================================ FILE: docs/partials/fluid-storage-disk.adoc ================================================ A {doctitle} is an item where items from the storage system are stored on. It has to be put in a xref:../pages/storage/disk-drive.adoc[]. The {doctitle} won't despawn when dropped in the world. == Uncrafting Sneak and right click while holding the empty {doctitle} to retrieve the various parts back: - The corresponding xref:../pages/storage/index.adoc#_fluid_storage_parts[fluid storage part] - xref:../pages/storage/storage-housing.adoc[] ================================================ FILE: docs/partials/processor.adoc ================================================ The {doctitle} is used to craft the various Refined Storage devices. ================================================ FILE: docs/partials/recoloring.adoc ================================================ == Recoloring You can recolor the {doctitle} in 2 ways: - Using a dye on the {doctitle} - Combining the block with a dye as a crafting recipe ================================================ FILE: docs/partials/search-box.adoc ================================================ == Search box modes [cols="1,1"] |=== |Type|Description |Normal|The default search box mode |Normal (autoselected)|Autoselects the search box |JEI synchronized|Synchronizes the search box with JEI |JEI synchronized (autoselected)|Synchronizes the search box with JEI and autoselects the search box |JEI synchronized (two-way)|Synchronizes the search box with JEI and synchronizes JEI with the search box |JEI synchronized (two-way autoselected)|Synchronizes the search box with JEI, synchronizes JEI with the search box and autoselects the search box |=== == Search box filters === Mod ID or name Prefix your search query with `@` followed by the mod ID or name to only show items of said mod. You can also give search terms after that, so it'll only display certain items of that mod. For example: - `@ic2` will only show link:https://minecraft.curseforge.com/projects/industrial-craft[IndustrialCraft 2] items and blocks - `@ic2 nuclear` will only show link:https://minecraft.curseforge.com/projects/industrial-craft[IndustrialCraft 2] items and blocks that have "nuclear" in its name === Tooltip Prefix your search query with `#` followed by the tooltip text to search for. === Ore dictionary (Refined Storage 1.6.x or lower) Prefix your search query with `$` followed by the ore dictionary name. For example: `$ingot` will only show ingots, because those are listed as `ingotIron`, `ingotGold`, ... in the ore dictionary. === Tags (Refined Storage 1.7.x or higher) Prefix your search query with `$` followed by the tag name. For example: `$gem` will show all items marked as a gem in the item tags. === Searching multiple items You can use the `|` symbol to search for multiple items at once. For example: to look for ingots and dirt, use: `ingot|dirt`. == Search box history Use the up and down arrow keys to scroll through the search box history. ================================================ FILE: docs/partials/storage-block.adoc ================================================ The {doctitle} is a block that provides the system with storage. It is similar to the xref:../pages/storage/index.adoc#_storage_disks[storage disk], but can be placed in the world. When breaking the {doctitle}, the items that it holds persist, so you won't lose any of your items. The {doctitle} won't despawn when dropped in the world. == Priority A (negative or positive) priority can be chosen (where a higher priority gets higher precedence to place items in). == Whitelist and blacklist There is also a whitelist and blacklist option to only allow or forbid some items from entering the {doctitle}. The whitelist or blacklist can be configured to be NBT or damage sensitive. == Mode The {doctitle} has support for the following modes: - Insert and extract (default) - Insert only - Extract only == Uncrafting Sneak and right click while holding the empty {doctitle} to retrieve the various parts back: - The corresponding xref:../pages/storage/index.adoc#_storage_parts[Storage Part] - xref:../pages/utility/basic-processor.adoc[] - xref:../pages/utility/machine-casing.adoc[] ================================================ FILE: docs/partials/storage-disk.adoc ================================================ A {doctitle} is an item where items from the storage network are stored on. It has to be put in a xref:../pages/storage/disk-drive.adoc[]. The {doctitle} won't despawn when dropped in the world. == Uncrafting Sneak and right click while holding the empty {doctitle} to retrieve the various parts back: - The corresponding xref:../pages/storage/index.adoc#_storage_parts[storage part] - xref:../pages/storage/storage-housing.adoc[] ================================================ FILE: gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: gradle.properties ================================================ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx3G org.gradle.daemon=false ================================================ FILE: gradlew ================================================ #!/bin/sh # # Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## # # Gradle start up script for POSIX generated by Gradle. # # Important for running: # # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is # noncompliant, but you have some other compliant shell such as ksh or # bash, then to run this script, type that shell name before the whole # command line, like: # # ksh Gradle # # Busybox and similar reduced shells will NOT work, because this script # requires all of these POSIX shell features: # * functions; # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», # «${var#prefix}», «${var%suffix}», and «$( cmd )»; # * compound commands having a testable exit status, especially «case»; # * various built-in commands including «command», «set», and «ulimit». # # Important for patching: # # (2) This script targets any POSIX shell, so it avoids extensions provided # by Bash, Ksh, etc; in particular arrays are avoided. # # The "traditional" practice of packing multiple parameters into a # space-separated string is a well documented source of bugs and security # problems, so this is (mostly) avoided, by progressively accumulating # options in "$@", and eventually passing that to Java. # # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; # see the in-line comments for details. # # There are tweaks for specific operating systems such as AIX, CygWin, # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. # ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link app_path=$0 # Need this for daisy-chained symlinks. while APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path [ -h "$app_path" ] do ls=$( ls -ld "$app_path" ) link=${ls#*' -> '} case $link in #( /*) app_path=$link ;; #( *) app_path=$APP_HOME$link ;; esac done APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum warn () { echo "$*" } >&2 die () { echo echo "$*" echo exit 1 } >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "$( uname )" in #( CYGWIN* ) cygwin=true ;; #( Darwin* ) darwin=true ;; #( MSYS* | MINGW* ) msys=true ;; #( NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD=$JAVA_HOME/jre/sh/java else JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi # Collect all arguments for the java command, stacking in reverse order: # * args from the command line # * the main class name # * -classpath # * -D...appname settings # * --module-path (only if needed) # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java if "$cygwin" || "$msys" ; then APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) JAVACMD=$( cygpath --unix "$JAVACMD" ) # Now convert the arguments - kludge to limit ourselves to /bin/sh for arg do if case $arg in #( -*) false ;; # don't mess with options #( /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath [ -e "$t" ] ;; #( *) false ;; esac then arg=$( cygpath --path --ignore --mixed "$arg" ) fi # Roll the args list around exactly as many times as the number of # args, so each arg winds up back in the position where it started, but # possibly modified. # # NB: a `for` loop captures its iteration list before it begins, so # changing the positional parameters here affects neither the number of # iterations, nor the values presented in `arg`. shift # remove old arg set -- "$@" "$arg" # push replacement arg done fi # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in # double quotes to make sure that they get re-expanded; and # * put everything else in single quotes, so that it's not re-expanded. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ org.gradle.wrapper.GradleWrapperMain \ "$@" # Stop when "xargs" is not available. if ! command -v xargs >/dev/null 2>&1 then die "xargs is not available" fi # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. # # In Bash we could simply go: # # readarray ARGS < <( xargs -n1 <<<"$var" ) && # set -- "${ARGS[@]}" "$@" # # but POSIX shell has neither arrays nor command substitution, so instead we # post-process each arg (as a line of input to sed) to backslash-escape any # character that might be a shell metacharacter, then use eval to reverse # that process (while maintaining the separation between arguments), and wrap # the whole thing up as a single "set" statement. # # This will of course break if any of these variables contains a newline or # an unmatched quote. # eval "set -- $( printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | xargs -n1 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | tr '\n' ' ' )" '"$@"' exec "$JAVACMD" "$@" ================================================ FILE: gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Resolve any "." and ".." in APP_HOME to make it shorter. for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! set EXIT_CODE=%ERRORLEVEL% if %EXIT_CODE% equ 0 set EXIT_CODE=1 if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: images/description.md ================================================ ![Refined Storage logo](https://i.imgur.com/Ro6lk7U.png) ## 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. --- Items 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. This 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. ================================================ FILE: src/generated/resources/.cache/59eb3dbb5f86130e09b3c62d89b9525ee01cf52d ================================================ // 1.20.4 2024-02-12T20:34:18.534056485 Loot Tables 24df81614f6b28c4c7e59589d79fd2c929d71727 data/refinedstorage/loot_tables/blocks/black_controller.json aadbec0f79a3fb95d39e866a453cfec0cbbacd36 data/refinedstorage/loot_tables/blocks/black_crafter.json a792eb6ac90ce775052c9c4a1b29bf9551477b5d data/refinedstorage/loot_tables/blocks/black_crafter_manager.json 8d35a75c3113cc686903be08841f9947a4e283ac data/refinedstorage/loot_tables/blocks/black_crafting_grid.json 012ad0521b80c1702b2bc3e40f497e7183d026d5 data/refinedstorage/loot_tables/blocks/black_crafting_monitor.json 4c0821c26133436eb65a6d3f9582ace6645022b6 data/refinedstorage/loot_tables/blocks/black_creative_controller.json 637e7efcb6f118e02ccff1ee8a4e942941c5f752 data/refinedstorage/loot_tables/blocks/black_detector.json 7999fa88db679231287dc5f26e6ec806e4f960a8 data/refinedstorage/loot_tables/blocks/black_disk_manipulator.json b50c133cdeb92695c8dce45b51ddcc38f62170bd data/refinedstorage/loot_tables/blocks/black_fluid_grid.json 63d1d4f37b3ffbeb4fc1ade464d75eecbd6d1bc0 data/refinedstorage/loot_tables/blocks/black_grid.json c4ae253974a27ea4a2eb4a1886fe1fd563662387 data/refinedstorage/loot_tables/blocks/black_network_receiver.json c9ac403f6e8cc119e2c0301a2986386458db8c44 data/refinedstorage/loot_tables/blocks/black_network_transmitter.json ee63465c82f3b6057724a18d4191b75d61e594fb data/refinedstorage/loot_tables/blocks/black_pattern_grid.json dfdc5c4b6a29d6d09a9f978ae72d416c747d49f5 data/refinedstorage/loot_tables/blocks/black_relay.json 57b43a2820cdc36a1149bdd09787a7ac93261f5a data/refinedstorage/loot_tables/blocks/black_security_manager.json e304e42fe33afc5255989a8e8d347024b1427128 data/refinedstorage/loot_tables/blocks/black_wireless_transmitter.json 0296cc57b6041564bb8fed5e0a932deb84d4bf05 data/refinedstorage/loot_tables/blocks/blue_controller.json a08dd8907fc5779207804aa2cb4193c9dd5eab1c data/refinedstorage/loot_tables/blocks/blue_crafter.json 56b6e9d582e51c0dca14235c419c8bf61c8af6ed data/refinedstorage/loot_tables/blocks/blue_crafter_manager.json a4302c275277be4cf7d0390e6d1ea0992416cf21 data/refinedstorage/loot_tables/blocks/blue_crafting_grid.json 0da6d20c18230429cec259adb30b4424c9778093 data/refinedstorage/loot_tables/blocks/blue_crafting_monitor.json 8a3784d5c3d51182678726274fcc79fdef70d498 data/refinedstorage/loot_tables/blocks/blue_creative_controller.json 050ec8e7340ec97b68f480d7c6901d7d5510dc60 data/refinedstorage/loot_tables/blocks/blue_detector.json 93e877f743d1ccf6bb6eba3c60af1554a429815d data/refinedstorage/loot_tables/blocks/blue_disk_manipulator.json 14921e4a33424e7441d5fd0b4fdc3668460b7e12 data/refinedstorage/loot_tables/blocks/blue_fluid_grid.json fb0553be84143db66f967729b738b2324e0dca77 data/refinedstorage/loot_tables/blocks/blue_grid.json 6447a482f3af9307a4fd8a8fd1a23cb875639b79 data/refinedstorage/loot_tables/blocks/blue_network_receiver.json 33e0950230a312281fce50d688678b2aff26a474 data/refinedstorage/loot_tables/blocks/blue_network_transmitter.json be8e6e5fea118107b59f89ce0f404b5fef9761a7 data/refinedstorage/loot_tables/blocks/blue_pattern_grid.json ecf55accdc040cada2d4e7eefda8cac6f2a4ce14 data/refinedstorage/loot_tables/blocks/blue_relay.json 673c38ad280709ac1662e8bc58a9f8229764b7f4 data/refinedstorage/loot_tables/blocks/blue_security_manager.json 08b72ed148b8e1728c58011ff0ddc8d5a466e940 data/refinedstorage/loot_tables/blocks/blue_wireless_transmitter.json b3237ea64098bd1fbf71c63fffc759093b874865 data/refinedstorage/loot_tables/blocks/brown_controller.json 914fbbb04e5f9bb9352d875afc3cd63d7abc9f63 data/refinedstorage/loot_tables/blocks/brown_crafter.json 3d3f99a92764bd9d89a40821c0851979b19d3971 data/refinedstorage/loot_tables/blocks/brown_crafter_manager.json 460b1ee39206de106a690b05a4a0a9b4a2f11b00 data/refinedstorage/loot_tables/blocks/brown_crafting_grid.json 18d4fd48da652f3399d464b86445e5dd80188b28 data/refinedstorage/loot_tables/blocks/brown_crafting_monitor.json eda5a766276ec827ef9d7f0cd6a5270d06036b37 data/refinedstorage/loot_tables/blocks/brown_creative_controller.json 86e9f01aa04c79323d242d46dc5f78663523fea7 data/refinedstorage/loot_tables/blocks/brown_detector.json 902cecd6312f228465cd2997070ae621db076fd2 data/refinedstorage/loot_tables/blocks/brown_disk_manipulator.json 95168aebbc23eba242dab32f7a3cb7ab88918839 data/refinedstorage/loot_tables/blocks/brown_fluid_grid.json 59ec70614a7a75b94522cb20c8e3462496f995bf data/refinedstorage/loot_tables/blocks/brown_grid.json ed0877cc6b64179d6cc13ebcca44d6b663d90e6b data/refinedstorage/loot_tables/blocks/brown_network_receiver.json 4a23a64fcefa7a944877c0df463989c39c7812ac data/refinedstorage/loot_tables/blocks/brown_network_transmitter.json 4770d6f0799098bb682bc2ef2779c9d6f5f706fe data/refinedstorage/loot_tables/blocks/brown_pattern_grid.json a5bf6fb6fd9deda0086a8f668f6df4b9a6968020 data/refinedstorage/loot_tables/blocks/brown_relay.json 20844d7fa89051d608178eac9557f56a3e8086b4 data/refinedstorage/loot_tables/blocks/brown_security_manager.json 9e012b0d20c6b027ccbaa244424c48ae1edab87d data/refinedstorage/loot_tables/blocks/brown_wireless_transmitter.json 13eaf1d8f3590c76ae60cad2b0e245946dba0491 data/refinedstorage/loot_tables/blocks/controller.json b0acafdeb359996979dda5951c75e93b533ed405 data/refinedstorage/loot_tables/blocks/crafter.json d39773a6d3f107a7068357d69936312e13811046 data/refinedstorage/loot_tables/blocks/crafter_manager.json 5d66d52291db34ac4b2f15572654a73e2f230d06 data/refinedstorage/loot_tables/blocks/crafting_grid.json 8ded2143b0001e35db03f982b69ecde40d8d8f77 data/refinedstorage/loot_tables/blocks/crafting_monitor.json cce990773ee788735e2a2b683e971b4b23d607c1 data/refinedstorage/loot_tables/blocks/creative_controller.json 67345bd6e3b6c0b8d508a7616181c3115e97cc02 data/refinedstorage/loot_tables/blocks/cyan_controller.json 20fc40541c376fd28727c7836cf7822400e0aa74 data/refinedstorage/loot_tables/blocks/cyan_crafter.json f0b8b0b499d202ec7e237f15b89ce1025e24339f data/refinedstorage/loot_tables/blocks/cyan_crafter_manager.json 2eab8b310091b32b0ab453b9debb156c23d200a0 data/refinedstorage/loot_tables/blocks/cyan_crafting_grid.json 7e4f01e9c94edbd6c216be21658f044340207df9 data/refinedstorage/loot_tables/blocks/cyan_crafting_monitor.json 11074d09ba1cc7c04b17b07f9f481b408d07a807 data/refinedstorage/loot_tables/blocks/cyan_creative_controller.json db6b92cae914d6e33b365da52b1d1a1a50b5d90c data/refinedstorage/loot_tables/blocks/cyan_detector.json 23dd314b2db7817a2a506a6ddcb6cd46828e98c0 data/refinedstorage/loot_tables/blocks/cyan_disk_manipulator.json 7ce3366b8ca5a0fbeb460118b4fe4511054343b4 data/refinedstorage/loot_tables/blocks/cyan_fluid_grid.json 40aac1ca0fcde10b0cd17bfd1fa21d9a0972e5dd data/refinedstorage/loot_tables/blocks/cyan_grid.json f05d82fea559ca7e2d45e246b577eaf6b5c49ba4 data/refinedstorage/loot_tables/blocks/cyan_network_receiver.json a3dc355c2a4c4d38a90662bf9ebaedb606d42280 data/refinedstorage/loot_tables/blocks/cyan_network_transmitter.json 4c5ceb9196f030d7aef1716556f205a7ce79c583 data/refinedstorage/loot_tables/blocks/cyan_pattern_grid.json c2d4acd3c98dd473b0d80b5961592a8d61f96191 data/refinedstorage/loot_tables/blocks/cyan_relay.json 295d129c7fd49180e9b14058567269571acda43e data/refinedstorage/loot_tables/blocks/cyan_security_manager.json 56ca30fdf4d256d1392fa90a474094a2ed81a442 data/refinedstorage/loot_tables/blocks/cyan_wireless_transmitter.json 156eabe81e2ac096f6ca34c39805dec8f1370346 data/refinedstorage/loot_tables/blocks/detector.json 1d5bc2eaa70e29576d05a2dcd1df639402c34b7e data/refinedstorage/loot_tables/blocks/disk_manipulator.json 107bc53a7e09fbbc5db214fe0c8a7679456b333d data/refinedstorage/loot_tables/blocks/fluid_grid.json 2ad4c836fac06bbee7121f506feec44dc1b7c65f data/refinedstorage/loot_tables/blocks/gray_controller.json b9857a36d6ee90f53c1c59df8fbc892359394e6b data/refinedstorage/loot_tables/blocks/gray_crafter.json 6ac770d2b9a4bc57efb306fe9aa94479fa6b4852 data/refinedstorage/loot_tables/blocks/gray_crafter_manager.json 0f0c0ed12a2d37258914f28b9b3d319cdbac158c data/refinedstorage/loot_tables/blocks/gray_crafting_grid.json 5e89a416f0f116493c95ced55cc77d14c7fc1e3b data/refinedstorage/loot_tables/blocks/gray_crafting_monitor.json 376724ab7bff219a1bc7d7f59141fd8fd79b43be data/refinedstorage/loot_tables/blocks/gray_creative_controller.json 894e4868a4b56b51df079b8d082a8a539c0aa349 data/refinedstorage/loot_tables/blocks/gray_detector.json ccce676f74305b63d7a45e76d1093d2881cc2d1b data/refinedstorage/loot_tables/blocks/gray_disk_manipulator.json 9e818613128f3e24f938ea39519998606b2f6107 data/refinedstorage/loot_tables/blocks/gray_fluid_grid.json ef34eceddddeb3777ba114d25a3b093bb1985139 data/refinedstorage/loot_tables/blocks/gray_grid.json 7463992e4ea9b61d3dbfcd81341dd8b756a94531 data/refinedstorage/loot_tables/blocks/gray_network_receiver.json 4f662f4d38ef075c010b0a337a2cd45c9710fcf4 data/refinedstorage/loot_tables/blocks/gray_network_transmitter.json ce1871ff8079907c0de3e50ceb40802145f98f72 data/refinedstorage/loot_tables/blocks/gray_pattern_grid.json c739c4afad2147f0902a1013d53da59e7eb1e656 data/refinedstorage/loot_tables/blocks/gray_relay.json fd4af6d41f5612a4ac464d465ad21dce414984dc data/refinedstorage/loot_tables/blocks/gray_security_manager.json e1353552c7aed55619efb3ed643fd33eadb13087 data/refinedstorage/loot_tables/blocks/gray_wireless_transmitter.json 2dd7488f69441e242618f0e9dfeb93abd0bc0ad3 data/refinedstorage/loot_tables/blocks/green_controller.json 32ccfda148ce86567f186607ae93b2c4117e8d7e data/refinedstorage/loot_tables/blocks/green_crafter.json d363818fcbcdd2c51401a534c00065d44fddc0e9 data/refinedstorage/loot_tables/blocks/green_crafter_manager.json e1e0d283fdaa6ff9904e1e60f005bedb767b0798 data/refinedstorage/loot_tables/blocks/green_crafting_grid.json 1d12d626542f20ad4c52ad9f6b6e87db8757b8b2 data/refinedstorage/loot_tables/blocks/green_crafting_monitor.json 56164ad40e03763835fcbb68d2ff9fbdf5e8171d data/refinedstorage/loot_tables/blocks/green_creative_controller.json d2ff277a9a0c37c996e042ce59ddc9c7fe1b92d7 data/refinedstorage/loot_tables/blocks/green_detector.json d10680065650631f22d28bc7aade92b2cbb4aada data/refinedstorage/loot_tables/blocks/green_disk_manipulator.json e0ce4fd2d89fd0e021dc7d52f48dd107a242f1ec data/refinedstorage/loot_tables/blocks/green_fluid_grid.json 5c4dff25ce16c01e1bf0fc0e0cd83f87ac195dcf data/refinedstorage/loot_tables/blocks/green_grid.json 71545b38180cb9bde153577f710bed49e86cbc1d data/refinedstorage/loot_tables/blocks/green_network_receiver.json 772a687694d40153439ee486788c1072c630dfde data/refinedstorage/loot_tables/blocks/green_network_transmitter.json 764ac435e57b29770189f5c7a792802540f4dd1a data/refinedstorage/loot_tables/blocks/green_pattern_grid.json 65321612e15b70f4feb7a0c682a13ed20e22008e data/refinedstorage/loot_tables/blocks/green_relay.json 95e279728c3bf38953213a3a3e8b4a3df84da9f8 data/refinedstorage/loot_tables/blocks/green_security_manager.json d64a37db61317d3c0952740116f231b94602b0d8 data/refinedstorage/loot_tables/blocks/green_wireless_transmitter.json 8686ebf23a0c2f933f83cb6199fe4df0caf20605 data/refinedstorage/loot_tables/blocks/grid.json e9ed2e584a1dcab850e7bae6c0dd92a872b278f4 data/refinedstorage/loot_tables/blocks/light_gray_controller.json 053a94f2151f2764149cf7d8aa54fc2e70b70c2e data/refinedstorage/loot_tables/blocks/light_gray_crafter.json 184c45a8c184817e1dbbd6feb03167f1fdcae7d6 data/refinedstorage/loot_tables/blocks/light_gray_crafter_manager.json de4a69f0aac181b36d60f145b2b35766b5a09401 data/refinedstorage/loot_tables/blocks/light_gray_crafting_grid.json 9dbeb212f1973177f8d46dd3e252ac4675c7d65d data/refinedstorage/loot_tables/blocks/light_gray_crafting_monitor.json aa648985c345347e5e01f8409c0f45727592c4c6 data/refinedstorage/loot_tables/blocks/light_gray_creative_controller.json 748f422c40c96f5bf2532ecb0d67d8d9fc2fde73 data/refinedstorage/loot_tables/blocks/light_gray_detector.json 4c4f9259bb20324d683bb3edd6601b6cdfd99d3a data/refinedstorage/loot_tables/blocks/light_gray_disk_manipulator.json 05b5b11c7a048ff3c00c48321d9b0d64ff28ba50 data/refinedstorage/loot_tables/blocks/light_gray_fluid_grid.json 4a850d2a9905c8977e6de3d21105945f2442de1f data/refinedstorage/loot_tables/blocks/light_gray_grid.json 3a83c78d233ba5d80a2cdbb293474fdab177b003 data/refinedstorage/loot_tables/blocks/light_gray_network_receiver.json 2d66d17b758a77419bb11b2ecdf6f4cd352e0d30 data/refinedstorage/loot_tables/blocks/light_gray_network_transmitter.json a85a5cc9a326b786474fb9efad32abc3d0afff9b data/refinedstorage/loot_tables/blocks/light_gray_pattern_grid.json d780c67d377d8c95afc37f00cf3b41bed969dd5c data/refinedstorage/loot_tables/blocks/light_gray_relay.json c47f072a53c7becbab85b2a1fa1e1bcb874f182e data/refinedstorage/loot_tables/blocks/light_gray_security_manager.json 34300f1c0f498b6525eb884dc828f7f08740644c data/refinedstorage/loot_tables/blocks/light_gray_wireless_transmitter.json 496511df85e27278e47953fed29d8fd799309e71 data/refinedstorage/loot_tables/blocks/lime_controller.json ca310f08455606ac4e396fd5bac020693bce6caf data/refinedstorage/loot_tables/blocks/lime_crafter.json b1423335fa0c8a09a9e259353399a503466224f2 data/refinedstorage/loot_tables/blocks/lime_crafter_manager.json ffd8c0eb615b97d850fcef854a769e493c4716ff data/refinedstorage/loot_tables/blocks/lime_crafting_grid.json 783e77a1007c4493722cfbf350ae87d4de3c7709 data/refinedstorage/loot_tables/blocks/lime_crafting_monitor.json 63df35073fd082358f319ddfa9151680c8c11a97 data/refinedstorage/loot_tables/blocks/lime_creative_controller.json 963a9cf50e1637f58168564b8a3e6c79b6f7df31 data/refinedstorage/loot_tables/blocks/lime_detector.json 5108afbce6b00ba5aebecf5a1b830676c9ab46e0 data/refinedstorage/loot_tables/blocks/lime_disk_manipulator.json 36c2b8de89a3be3b9c94eb888172f14c597397a1 data/refinedstorage/loot_tables/blocks/lime_fluid_grid.json 3f06f52d23473176254ded743c65f1a0f705c274 data/refinedstorage/loot_tables/blocks/lime_grid.json f7f89777329a9947b78d44aa598130eeeaf46e56 data/refinedstorage/loot_tables/blocks/lime_network_receiver.json de0bd3f51fb36d84a1e878e1c245873fdf8d5092 data/refinedstorage/loot_tables/blocks/lime_network_transmitter.json 7f6e0347cd73c6c32f049bc24b31615774bafb5c data/refinedstorage/loot_tables/blocks/lime_pattern_grid.json 54b79f03c436a14c01c7336ea7990737c7f0d1a5 data/refinedstorage/loot_tables/blocks/lime_relay.json 224b225bcfdc170f0e252f5b24cc3ad1cdd22c35 data/refinedstorage/loot_tables/blocks/lime_security_manager.json 8a1c7b13a82323edf98d35dea2d58a7f67f1be1e data/refinedstorage/loot_tables/blocks/lime_wireless_transmitter.json ee7f558dcd74223058695bd556e7c9fb4822ab1a data/refinedstorage/loot_tables/blocks/magenta_controller.json 6c9af4551b92ab22898ef23c97c800fd9f9ecfa8 data/refinedstorage/loot_tables/blocks/magenta_crafter.json eb99d699ca7fc009e42c9b1ade0cfd15f01a9318 data/refinedstorage/loot_tables/blocks/magenta_crafter_manager.json b62eca644682ccb4330ce0bb859887a3699d0e20 data/refinedstorage/loot_tables/blocks/magenta_crafting_grid.json c83c3e0c58d11f59777a19417aa95f4d875471a8 data/refinedstorage/loot_tables/blocks/magenta_crafting_monitor.json e17fd6f969351f971c45fb4d57d4df9e281f9ba8 data/refinedstorage/loot_tables/blocks/magenta_creative_controller.json 6a953eb2d9ca8af562bb0d45fc2fe36b40cabb6a data/refinedstorage/loot_tables/blocks/magenta_detector.json 1301940aa011c199a3317cd69dd6eaf0b1620e54 data/refinedstorage/loot_tables/blocks/magenta_disk_manipulator.json ffdede2468925a2b10dff6bf5af3b1431c0ca9d8 data/refinedstorage/loot_tables/blocks/magenta_fluid_grid.json d7047c8c229ede6bf7ac65047603d25e6f1ed2a2 data/refinedstorage/loot_tables/blocks/magenta_grid.json b815c5765403df1462e93a6071ff09cbba46e475 data/refinedstorage/loot_tables/blocks/magenta_network_receiver.json ac54dab195ac0ab0f50a2839d294784f0521f31b data/refinedstorage/loot_tables/blocks/magenta_network_transmitter.json 400364c11c26cd3d8f7b71b5ae879fa1d10663fb data/refinedstorage/loot_tables/blocks/magenta_pattern_grid.json 70fd6ab4e7a23fae99b040cd9af85fb3c45b9ccc data/refinedstorage/loot_tables/blocks/magenta_relay.json eb72984254ac782338bda19317d843137c19c275 data/refinedstorage/loot_tables/blocks/magenta_security_manager.json d14a7e2df81a8227effd234e29d7463aa736d567 data/refinedstorage/loot_tables/blocks/magenta_wireless_transmitter.json 3b996feb6bb950269703c8b8c739631146ddc9ab data/refinedstorage/loot_tables/blocks/network_receiver.json b6fff20f89fe4b20fadb246103f78a02076d6e31 data/refinedstorage/loot_tables/blocks/network_transmitter.json 9b81c9aa19ae65d547fd9bfb517022eb9999d9a0 data/refinedstorage/loot_tables/blocks/orange_controller.json 1bef1c8c51963a2e3d6c165fe93d65e6cdfd223e data/refinedstorage/loot_tables/blocks/orange_crafter.json f9a701ef8fd365eb00036f7386d1e7fef483ffdf data/refinedstorage/loot_tables/blocks/orange_crafter_manager.json b052347226c701e3fbd6fcce2704cdd6a5eec7d2 data/refinedstorage/loot_tables/blocks/orange_crafting_grid.json fa4e843e3ece45877f5aa4eb581bb415bb843b2e data/refinedstorage/loot_tables/blocks/orange_crafting_monitor.json 2c5fdb4fdcbeceda862b78415a46d544d6c799e4 data/refinedstorage/loot_tables/blocks/orange_creative_controller.json feed8d697c60b9e3f5c350495dd09d88c5166186 data/refinedstorage/loot_tables/blocks/orange_detector.json d6bed8b23f4f4ca4423e8c7ec2c7ef6508c73883 data/refinedstorage/loot_tables/blocks/orange_disk_manipulator.json 8b2b1669f6de2119226e7aac025930bbf0547786 data/refinedstorage/loot_tables/blocks/orange_fluid_grid.json 47d683086d96acd03df1e0a3f39d1650f5042f43 data/refinedstorage/loot_tables/blocks/orange_grid.json 6028ef5f54524256be2614bf74e6d5a2cd9f37d8 data/refinedstorage/loot_tables/blocks/orange_network_receiver.json 5eb2338f90194901fde0223b2b8f9cf4df7a1dc5 data/refinedstorage/loot_tables/blocks/orange_network_transmitter.json a345f55acce3a08adcfa989b466e665b132eaac5 data/refinedstorage/loot_tables/blocks/orange_pattern_grid.json 05f957b8c247c9ff8e3a52ba2e9eacda9e833901 data/refinedstorage/loot_tables/blocks/orange_relay.json 40e68229e3680b257c6d27393e3605099d3e1d2d data/refinedstorage/loot_tables/blocks/orange_security_manager.json 3b406197bc87c8eee2ffff10a3ad8a6b26dd26e1 data/refinedstorage/loot_tables/blocks/orange_wireless_transmitter.json e734a87e44a3ab72b839061e2c410b280976abf5 data/refinedstorage/loot_tables/blocks/pattern_grid.json 7d432b1ca2685d96c5a075eb627c643f1c238478 data/refinedstorage/loot_tables/blocks/pink_controller.json aabd2cb525aedd90574528aac116e616febae44b data/refinedstorage/loot_tables/blocks/pink_crafter.json f95958233f8404103e2e3b12a1f67c65bcda91ad data/refinedstorage/loot_tables/blocks/pink_crafter_manager.json c6008a683980e41ecfe85e6eb28b5172e8ea1647 data/refinedstorage/loot_tables/blocks/pink_crafting_grid.json f2b276ed4fcee2b2496f618865b81ba9d20ef349 data/refinedstorage/loot_tables/blocks/pink_crafting_monitor.json de731f64d79adb6d72a7718fcbf8a08057364429 data/refinedstorage/loot_tables/blocks/pink_creative_controller.json 1fa8402228b423d6837db0f0f0a89b2b977386e3 data/refinedstorage/loot_tables/blocks/pink_detector.json 7b6aedb2e39cfd039c12fa965e544874fec3bb6e data/refinedstorage/loot_tables/blocks/pink_disk_manipulator.json 8b68b1adfaf61ec47065b240780486093fa44d8d data/refinedstorage/loot_tables/blocks/pink_fluid_grid.json 5aad68b152ce93baacdd3782e9741a23a86bff66 data/refinedstorage/loot_tables/blocks/pink_grid.json 1cd050c613c6ebf27dbc7b600b35ff5209c92da3 data/refinedstorage/loot_tables/blocks/pink_network_receiver.json 1ffe3968b44d6412c7d46998b1b8dceb059d8e38 data/refinedstorage/loot_tables/blocks/pink_network_transmitter.json 4a23c78a95c2a5d8acc68fc6f291565b209c7a9e data/refinedstorage/loot_tables/blocks/pink_pattern_grid.json 467014d74cf161a2c3a6361a8ee6c22533ce55f2 data/refinedstorage/loot_tables/blocks/pink_relay.json 64038f767f4cf1328f997b40bb40a172d13b8c55 data/refinedstorage/loot_tables/blocks/pink_security_manager.json c07f1e1a05d68d8a35b1fc5dcd432cf8b578e2cf data/refinedstorage/loot_tables/blocks/pink_wireless_transmitter.json f0e9df045caf7a2a5ab026acaee0c0b63467459d data/refinedstorage/loot_tables/blocks/purple_controller.json ecf72bb58c1416d231041cdf6597d5985ac3bf63 data/refinedstorage/loot_tables/blocks/purple_crafter.json 58b286402377dd10c026710ee30c6c3210a65a07 data/refinedstorage/loot_tables/blocks/purple_crafter_manager.json 2427fc724d952fc259157b04e7e47e9a9adf9aef data/refinedstorage/loot_tables/blocks/purple_crafting_grid.json 913e0ef93af29c19bbefe95061b5a95894b3d77f data/refinedstorage/loot_tables/blocks/purple_crafting_monitor.json f3175f9f9415c65280c9d43a8deae5825afecdbd data/refinedstorage/loot_tables/blocks/purple_creative_controller.json 8281ca3173c8f137dca52f4d8b15e8ae62328323 data/refinedstorage/loot_tables/blocks/purple_detector.json 69c32db236c4a4c5ab97f17f1b6c7e9470c24180 data/refinedstorage/loot_tables/blocks/purple_disk_manipulator.json 6a5cd1a241a9824a80020daf0bdf86b36eebf2e1 data/refinedstorage/loot_tables/blocks/purple_fluid_grid.json 91c69a86c61dfaa9183548f9a4b9d3bb6d457ae6 data/refinedstorage/loot_tables/blocks/purple_grid.json d142bb7058ad7ab11a69fa3cdda0d493dd0fd8e5 data/refinedstorage/loot_tables/blocks/purple_network_receiver.json 12410d1595702c613b4dd65e1292e604c808e002 data/refinedstorage/loot_tables/blocks/purple_network_transmitter.json f40cad0e109abd767ef8dd083f29ecf81eec4021 data/refinedstorage/loot_tables/blocks/purple_pattern_grid.json 7b2a23a5f7d5ef7768dcad8f1e1dddbed80911f0 data/refinedstorage/loot_tables/blocks/purple_relay.json 447952f40fbbce47c420ea597a23e6c93ef38efe data/refinedstorage/loot_tables/blocks/purple_security_manager.json 9ba20dab86f37397695805c8db0f572e96e541b6 data/refinedstorage/loot_tables/blocks/purple_wireless_transmitter.json 43229da34d37f4560833a9742b3f4b6138da89b3 data/refinedstorage/loot_tables/blocks/red_controller.json 056331455eb87d28a0cb1659d0724282a4ea1449 data/refinedstorage/loot_tables/blocks/red_crafter.json 3972629af5458ffb1c03cea0740e62a78a7b2666 data/refinedstorage/loot_tables/blocks/red_crafter_manager.json 9fb2d4f0c6bed2c9060f4aebe78475ffb75cf83b data/refinedstorage/loot_tables/blocks/red_crafting_grid.json f75544f8ce7efc64fb91d354af1d5f50dda4c9a1 data/refinedstorage/loot_tables/blocks/red_crafting_monitor.json 22c7826e4cec1b9fd4756427bf1a3b0b187c52df data/refinedstorage/loot_tables/blocks/red_creative_controller.json f437c5db37d754b96df4dd9c7761f3412b9a3e53 data/refinedstorage/loot_tables/blocks/red_detector.json 9ce161f040fa06eef72775d51f531fd07bef6ed3 data/refinedstorage/loot_tables/blocks/red_disk_manipulator.json dd1f509da29f69f311d66deb6becf87e75be7e57 data/refinedstorage/loot_tables/blocks/red_fluid_grid.json e1cb6154faac93b2ca63f1a3c8d894361a532b58 data/refinedstorage/loot_tables/blocks/red_grid.json 02f5ccdccc47354ca9690b347f32a96f5b0051f2 data/refinedstorage/loot_tables/blocks/red_network_receiver.json 600ec0b5ee923cfb7f8ed9d14e24b132660cb413 data/refinedstorage/loot_tables/blocks/red_network_transmitter.json 2e79450eba074c46756b16be391901f2b89daa48 data/refinedstorage/loot_tables/blocks/red_pattern_grid.json d20b27a7c016c29a431eb70542110a1e7f4ef797 data/refinedstorage/loot_tables/blocks/red_relay.json 3c21b2588322b43c7ceb5b8ef276416c0aa972af data/refinedstorage/loot_tables/blocks/red_security_manager.json baa1d85de292567f37bb3c4fa082d5f202caea19 data/refinedstorage/loot_tables/blocks/red_wireless_transmitter.json d2f04a0605843de064981d3ee6d2b7e782c37356 data/refinedstorage/loot_tables/blocks/relay.json 6cc2e8ee53e0bcf6753c2d8d69a9891b27110eb0 data/refinedstorage/loot_tables/blocks/security_manager.json 1ca249351ca9e410362047b3502e3b4e32613cbb data/refinedstorage/loot_tables/blocks/white_controller.json a0827f3368539eb492d03ff2f8dbc98d530add20 data/refinedstorage/loot_tables/blocks/white_crafter.json c40e7a90edda22be3940886ee5246677ef82c09d data/refinedstorage/loot_tables/blocks/white_crafter_manager.json 045e2477745e4972ff05638a8191755dcb1766b0 data/refinedstorage/loot_tables/blocks/white_crafting_grid.json e465dc037c72ffbe767857ff51d0c20dadb37e72 data/refinedstorage/loot_tables/blocks/white_crafting_monitor.json 7d8f3d222b0f155c0f31e6c0f8b456cfc0626701 data/refinedstorage/loot_tables/blocks/white_creative_controller.json 8475b4c7c0ca24facdd93443761d032fcfa4d240 data/refinedstorage/loot_tables/blocks/white_detector.json 04a87335b56c2935578c64257b534fcb0c6ccaf5 data/refinedstorage/loot_tables/blocks/white_disk_manipulator.json 7d84c9cbcc4dba2429375001785ea4730baf985a data/refinedstorage/loot_tables/blocks/white_fluid_grid.json 9e62382949bfad25fd8c83ec0973d4e7297908d2 data/refinedstorage/loot_tables/blocks/white_grid.json b355304a9aeb739c07d9f9f4c3eed2238423c37a data/refinedstorage/loot_tables/blocks/white_network_receiver.json 4dd2e115fa2d37ad228fe037693fdfb7f3a6d74d data/refinedstorage/loot_tables/blocks/white_network_transmitter.json 130caa289363874ab2dc96a9c3171be4bd4a4140 data/refinedstorage/loot_tables/blocks/white_pattern_grid.json d7d36879c59cbeebfa0851e428ef6252e04128e3 data/refinedstorage/loot_tables/blocks/white_relay.json f990de5e3803c7a3c620228fb398e25a84a98524 data/refinedstorage/loot_tables/blocks/white_security_manager.json 1e8bc1858a3dcd0bfaa5b2a5d13bcdec0dce5438 data/refinedstorage/loot_tables/blocks/white_wireless_transmitter.json b6211ce48a7aef9cbd64f4435ad43b41cdccaaff data/refinedstorage/loot_tables/blocks/wireless_transmitter.json 8009a288908306e879924346d0d4d5f2123b88a0 data/refinedstorage/loot_tables/blocks/yellow_controller.json 641acf6da9b5f838171a42bae45dc19f0fa51299 data/refinedstorage/loot_tables/blocks/yellow_crafter.json 74f175474b5f74c4139b0c85deae09104ed3ef1a data/refinedstorage/loot_tables/blocks/yellow_crafter_manager.json 33fc0a6833d600569ded23cf55dc4c8e2a0883c4 data/refinedstorage/loot_tables/blocks/yellow_crafting_grid.json a600997dc1478e5d290f171ebbdb42a5a86501d3 data/refinedstorage/loot_tables/blocks/yellow_crafting_monitor.json dd06b6d13cec49ac1290f89d3ce232daba4fdcb7 data/refinedstorage/loot_tables/blocks/yellow_creative_controller.json b04dae60c3996c52d86ebaa5a6a876afb5faa536 data/refinedstorage/loot_tables/blocks/yellow_detector.json a9a6c1a6f9e145dc6f55b6acae994983c41f0918 data/refinedstorage/loot_tables/blocks/yellow_disk_manipulator.json 352d37f7117556cb2c53de4b0846e8ef5ee84682 data/refinedstorage/loot_tables/blocks/yellow_fluid_grid.json 80659f567c1fb6fdad99f9b79522f2b25d1365c9 data/refinedstorage/loot_tables/blocks/yellow_grid.json 288f81f67a969225f871be891af29ff90cf86ea5 data/refinedstorage/loot_tables/blocks/yellow_network_receiver.json 5c016e53badfba708081c8c21e000e7cb591ad7c data/refinedstorage/loot_tables/blocks/yellow_network_transmitter.json ec629e7f9a1efb517c49e38666e27f141c0c815d data/refinedstorage/loot_tables/blocks/yellow_pattern_grid.json 9a61fb36d749298451e7baec7ec965b91fb3a142 data/refinedstorage/loot_tables/blocks/yellow_relay.json f7111d534c44737bb7f8e8e15c6484b314a10dc8 data/refinedstorage/loot_tables/blocks/yellow_security_manager.json 3d20f6b4a0f17c42d79516f2bf66647154ef57e7 data/refinedstorage/loot_tables/blocks/yellow_wireless_transmitter.json ================================================ FILE: src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e ================================================ // 1.20.4 2024-02-12T20:34:18.538076766 Recipes d350b2771bd4ad63c80d048da51e610005d6daca data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_controller.json 54840c4b526d0652d376bc75f06930142b6ee47e data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter.json 23b7a5b786b618c8061202dba92bf6751510b15b data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter_manager.json b15e62f2c4fe216e157e898b53c0465d4f173a84 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_grid.json 97005bdb24b1113ec6b6d89749122d223dfa9356 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_monitor.json 55622084b126567c34634c919496ad17b9bf90f2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_detector.json fcf26564563a2e04e74f411d4d7bf7f3f459e193 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_disk_manipulator.json d7bef08a9c37f96bd17943d97489ff4b758f0608 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_fluid_grid.json 2b443003f3344edf2b0d7822868a6cc8fcd16089 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_grid.json 43455ac450834a527402617e5e57a4017ebf0316 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_receiver.json f51c17ad3c15121e2ecac366ee763cd448b3c4bf data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_transmitter.json 30fc6bc4416522b5478ec7f45fda0444cf677b05 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_pattern_grid.json c4f162dee00f9d2f0c3d067c6c392873432bc20f data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_relay.json 9dcbbdb26e0c2e2a5365c65e86d5975c233d7cbf data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_security_manager.json 529c5dd81a44add1cdad7fe4535f379532fc68b5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_wireless_transmitter.json d26368b812c74eef2c0cd62398d00b749dbeab32 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_controller.json 444ae3b86d615aae2c496cd8a4ea4b5ad72d265f data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter.json b35122d76b4bb806a71934b073749208072acc25 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter_manager.json db19bc28ee75d480ce92a6fc8378c4050cee63c1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_grid.json 62f2936fba8519e449a2025bcfc2ef0a34586b79 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_monitor.json a2eb10818ed380108e7baed01fc01fb29958cee6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_detector.json c9ee2feb3892a37a097d2ed726913138ca2ddcde data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_disk_manipulator.json e42c45ebfda407bc8a63b6707736f1d9fc5d0ba7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_fluid_grid.json aba1df8aef34cd1d4c65784f1b85735b716167db data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_grid.json 399944bc9e7249d69b21dc76cc6efb43e60746d1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_receiver.json 9552d403b622ceffaa8adbb67c1ccdd994c5761c data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_transmitter.json f1ae7f1ceb705970b9f3b6069d09d23a14c3ea83 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_pattern_grid.json 11777e4d00ad8cd996669a38771bd6107cf9e218 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_relay.json 558e83123713433b9218a73e5d73fb77319955ea data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_security_manager.json 8bd0fd506e240f8f52722203d3ef0b2e991eb7c2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_wireless_transmitter.json f331f32959b42fd8ec8b029f6280db5ccd3cb2b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_controller.json fd01b544422d143849c67deda5ca42837c1ca398 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter.json 54ca4eb21f728930d7ec85f0c71751098df068e0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter_manager.json 0abe0f9c101ef02e32e5bd156788019fb84b9033 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_grid.json defa0fd4df43b104b12ddbe58fe4143388a1fb37 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_monitor.json 2286d49a53f5e9e9950f7b3493bc36d21b8156f0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_detector.json d1c01332b1d6d71471307d8ed317b7e4af5faa8a data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_disk_manipulator.json 326b68bbffd81f01702f92cccf2f2cc30b905c40 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_fluid_grid.json efef6095e9e358abedd58e5a30aebfa730b61b93 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_grid.json 82cf9f104a4f196a41a4623c4374e948ac790231 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_receiver.json 58255d690b0900e394de5db9d5bfcce218121398 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_transmitter.json 4aaa821eab15d6e1797db5e11c1b1aedd1531c57 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_pattern_grid.json 45a34a412a792f74b6a2a1110343879329a888eb data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_relay.json 17292d3a1960cf27224ff3be2f0d489c994616b0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_security_manager.json 120cea1d066a276ead272fd65f6c87d67a4c51a9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_wireless_transmitter.json ec1f6d949021b377481cc85f3c467ce0a22773de data/refinedstorage/advancements/recipes/misc/coloring_recipes/controller.json f308296bcfd82dbe8ec0b16fd8676695b5507b05 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter.json c2799d9f2a96b93ae0a5a44a3ca19f8b3d118829 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter_manager.json 08fa572f80f7950cd44f45226e6674277d6302c1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_grid.json d04b75de8d7beed6a9fb4b95c76fb2e7372879d2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_monitor.json 7279fc15ca132eed3ec3b98d8d8b4000a8b946e0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_controller.json 81d170036872e1aa35773cfe1a54e9ae25e3c8bd data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter.json 22d75217a257c2bfde3faa9042016391fdd1a881 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter_manager.json 0c1d56d7620d98e018103bb8bd6a1ac4a6ba8f8a data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_grid.json a049e2fa95f344d566a3b4e9a8bb723f361d3b22 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_monitor.json 46e2401b27b24f2daa3f92be57bd0917efc1cd17 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_detector.json 69361419882d5b0beb1e2c97dca3fb5333e96006 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_disk_manipulator.json 38e3aba8366c111c322c25f33afd1e05db0495cd data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_fluid_grid.json 4df118e5e0a7f3d44b13c29b6e17fdc74375e4f3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_grid.json fd921c19c96c88f248cb72066bcdaef5244d0e29 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_receiver.json 78b6a92c183db89ec7ed784752821da4663c53f5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_transmitter.json e41899b7a205cc933ddbae98de06b2eb56d7fc61 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_pattern_grid.json dac4aa9f73456bfa0d589a997980f7cccbca01f9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_relay.json e29e96cf471a1f3751358cb4847fa34e95d02ca5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_security_manager.json cb4c05ab919c0bc0a83def453f74e6f783b9dff5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_wireless_transmitter.json d55193c421a69c24dd64d98ac3154a433a537325 data/refinedstorage/advancements/recipes/misc/coloring_recipes/detector.json 3e89a210043d9e41dd2165f0e73548e1884c2232 data/refinedstorage/advancements/recipes/misc/coloring_recipes/disk_manipulator.json 81d30c747d62a729c195c55435283dbf9ec3ccc6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/fluid_grid.json e8cf20a95b3bf091612098b3c516a5189b8d6799 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_controller.json e77cdb0c96a755fab508295cbc021a4198a73a32 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter.json 8655e0374baeecefd17e45b8b3bdd500d898497f data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter_manager.json 29049edb4edc8f183401d42fe90e56e796b9f524 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_grid.json 74feb00efdaa6bdec68d6d98fbdfe20d66f89178 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_monitor.json 2361ea074be45b6d5bc156d92765cfe95d005927 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_detector.json 80a4d154d21b70a184eac395a5a7b72d209de429 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_disk_manipulator.json a25f5655c5b77acadc21f13bb6386738d5bfbbd2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_fluid_grid.json b0e993da2cae346c1314ede633f8e01b88000a9c data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_grid.json b47265fad6beae6b7e8902c8b8711b8c4b1c3f67 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_receiver.json 8c1027dfd8d0f024c4cff7888a06f4bf28ff2ceb data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_transmitter.json 2b14eef6f0640ef29b10b0496b3b2e03a8401efb data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_pattern_grid.json b9ba15b383fc750bd8f51fbe757ac398be229979 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_relay.json ba0ff95eb1d047d4045d27cd67ed2b74e1faade2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_security_manager.json 93194bde577130f3aafd15968ccef34fdcaa0994 data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_wireless_transmitter.json 5b494d4de2d8e760868080a3a47e6d9ffa6d2d97 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_controller.json 23166b7d06c90415a904b874ecec4ef3b76d376b data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter.json bb271c810fd9010232efca4a44faad9d4a9cd90c data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter_manager.json 081abe762fb4198d49a0baf0858b5d2fe37a1595 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_grid.json fa2567877f0fb5bb02a5831ee137aa66ac47dfe4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_monitor.json 0e6a77a42153aa2bba05e96c5c553114c4c718b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_detector.json 43321a147268c573478497f2aaf5e26baa044859 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_disk_manipulator.json e08307b008e993464bfa52815a2673fc057c6d49 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_fluid_grid.json 504bb9ddda37a8ef76c7765de0f2a2e24f7b0171 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_grid.json 5d72547ae9d1d014cd8f922dc045eafac843698e data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_receiver.json ff769707888be7b3d0233f664ba7129f37c9f5bc data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_transmitter.json ce4880ad86cacb787dfb3c20eab27c01b0a7f3f1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_pattern_grid.json 1b5141b4908766b25af9b1d4a2cf5018957f25d7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_relay.json 33854d93ce3dc17717ad234d3dc875a69841c9ad data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_security_manager.json 7008d4ec46c9c0995e603648d347438232749296 data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_wireless_transmitter.json bf27477c47f4f5af6b5a8adc4e177fdf5794afcd data/refinedstorage/advancements/recipes/misc/coloring_recipes/grid.json 3541bc5c522700de1004183d7dbeb9721749f99d data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_controller.json c4c71c447d0170c3ff20d777fe7983d9bcc799bc data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter.json 702b34d1c0dbec4956f82a622d95f581135a5cc1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter_manager.json 5926515e95f7faa6e81bdb539f1da4b7922bdc22 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_grid.json 7113c0865a37a843238c0bd618656575f5b8613e data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_monitor.json d9de193424b692af7724bfa428dde79463c94083 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_detector.json beaa78d1ca605357c665cb6c077a1aa1695eb2c7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_disk_manipulator.json 0d62c18cd86e523a197e84ffe15fdb2fe6444668 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_fluid_grid.json 4a92ca1f1cb915269db078ed1bd14d90b024a7a0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_grid.json 212af37ca0be812f405238fe913bcdc33fdee9a5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_receiver.json e6a7aed89254fcaaf24eb42897e6d853fa9cbbdc data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_transmitter.json 9afae748bf4f8539db59bdfe6bc77ca7d1f94a8e data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_pattern_grid.json a83096cbd33db7938aaf28cfadedcc6227d1dfab data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_relay.json 196951d09482eba275eea65407da6f3f9ef659a2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_security_manager.json 6862bcabca8ac284dec0ca21113d2a47fe2a25c4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_wireless_transmitter.json 8920ad0af9501e05ae67a18c185422ea3f2d494f data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_controller.json 4f744de464eeab733def439030ec568704dbdfc5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter.json 704dc694a1392918c9df6f1bcb711cae74d09bf7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter_manager.json 65f7d805a7fa684271d1232f532886c31caf08b8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_grid.json b665f849378bcded92f27612b5ee4714a2bdb3c8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_monitor.json 1d2b1bde350c014d31a47e2acd64344aaf39f006 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_detector.json a2fc75ed0e55da1a09b5e4f7d0d3d1f932b20296 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_disk_manipulator.json 6e48a78e9a261f218bcc530f4f2f9bf8d1f5b7b0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_fluid_grid.json 382df921efdc89d06e6570d96456200893701847 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_grid.json 0e2f9c833b32dbbb9cc994d5331e201f646e2260 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_receiver.json 340e02a24ca341d029fe6eb0edf54527456b6fca data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_transmitter.json 7ae8303f3b8d083ac253629732fe5843d98a46ef data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_pattern_grid.json a9d8202520a2eeb40036b4f08b2906a235b26c7e data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_relay.json d76d10c59fdf4c3faf6736f788d88eeb1c361fb3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_security_manager.json b7468157902e6a9f332b038e0b6a104243ed3824 data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_wireless_transmitter.json d5e5099a140396ad770fc1e080b06ae58e5bab53 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_controller.json 0d738a1bcb7f70d0c8a2fb8ddc58106cf1f1af56 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter.json e71700d2067eda969cff274b75fa06abe55e5456 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter_manager.json 8cdad9ed6a81ae38b39ff89e3c8b8a3162591ec4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_grid.json e889eb8c665ecde9fd814aeae186c33fa9fe774c data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_monitor.json ed8f2c1dfbb3efdaf9a17abd528ddc4fa9c4351b data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_detector.json a1eaf5560aa797a920c6d859e1da12f26df70ba0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_disk_manipulator.json 9337dd604b42c894ec795ea4d933494eb6cd3ffa data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_fluid_grid.json 3b5787043fdf9470c94c55a1ec4e2332ec7e92f8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_grid.json f47530ed35d85cff56678f2848f508e16d5d754e data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_receiver.json 75c0c87f36745c83d7d7afe95ace7fab776bf049 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_transmitter.json 6480e36774a962568474a4ebace57436f841d105 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_pattern_grid.json e637d70e432940ff585c3bff26e9883ab61243c8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_relay.json cfe2c6806954fa84c96a886883617ade1920cba4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_security_manager.json 27590375ef521bd3dac015c46483e8a14e6d518a data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_wireless_transmitter.json edf871954047dc82a5baa504f093c8bd95bc9e4f data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_receiver.json ff22d01d0549186d21c65245d7a8647cb3e8d831 data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_transmitter.json 7a1e7c7acf6c5e517a825c416354b1c52993e8e8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_controller.json 146baa694f6912ec9b34d0f9f0c94fb49b7a66c6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter.json b53f5da5a6745f0ab4479284a5b238e52d23af31 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter_manager.json c6a0b5ad7a2701caa7f185b2445730d8de2d8231 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_grid.json 77ab4c02e39cf139fa110a5543e6c4121d095959 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_monitor.json 5464c441ae2378ff8cf655bf092698e8e5cc6698 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_detector.json 6212064e3078df7b4b2f0eaf2c66b2351afb8d75 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_disk_manipulator.json 9fa3953437f41825a1a94cfd8b26ad0deba512c4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_fluid_grid.json 3da19d71780bb0dd8b598680f0f6cdf51d095a5b data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_grid.json e8c6ea5c6321cb3f0c0818a7f20bb34dd19d6b8b data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_receiver.json 599372e90c5525ba6965d85bad3dc598684cbce8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_transmitter.json c89d2ab0fc65018f61c6e0db371d1b91fa0dc304 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_pattern_grid.json acc414b2be65c1bd89fb1236627d418eb3359095 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_relay.json 50b1bbd95f32b7f79fca433d06c7cf9d312ff635 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_security_manager.json c6e2ba623ce6e0ecc93357415ed1c33190cc9416 data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_wireless_transmitter.json 1bfff6f3c7fef860a7813bb3f6196605b47de77b data/refinedstorage/advancements/recipes/misc/coloring_recipes/pattern_grid.json 230c5ac17bd397b63dd54c22a6b1f4d5abb1f6c2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_controller.json 64ae49fdeadba8df9bc5cfc01aaf84c757265fa1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter.json d49b9aa96ca0b53f42f13c133141c903608ca66e data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter_manager.json 787fb6d515ef4e04abe1ef518634b93d862642ae data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_grid.json 1920557334d4fa98a37d154f4bc8ddc242d3c278 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_monitor.json 13223e633b19fdaaaded08f0a645b352cc2ad754 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_detector.json 13f2066a6766b5eb76eaeb9b8c2b443ae8ceabde data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_disk_manipulator.json b6531737768efdf4fd516609f5b7e26c3c626995 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_fluid_grid.json 3102d2be9e0ebbbfbf433b6758fb26cd538f8f3a data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_grid.json 13a94375a8af3ef1752f87fe175a4004b1f222ed data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_receiver.json 3c60279b49941739ee15d5ec8300e0509afca26d data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_transmitter.json d3839fb0c7a92432e930bc3a9a45dc4b93afddf0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_pattern_grid.json 0b690f7621a8a70fe15da08d0c5b4353f132a510 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_relay.json 96915b3461232a2b27887fdbba7752c8dc14d532 data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_security_manager.json 7c308ed13a18f4ce573e1d335ace88f8785fbfdb data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_wireless_transmitter.json 8c81dd70017507b21aa84af1d133c5bb9e0354b1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_controller.json b70a31b425cd286d3e5852c67c35b3c5cc8f1204 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter.json a63197c094c15d3d07f6dadcedc5cd5cacbcc6d6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter_manager.json 38928bc5a96a0b17e98957e5fdaa09315ecea8fe data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_grid.json 239fb41ac609b312e47800ab6b244ad2ec011694 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_monitor.json 4088a819616dc7de931babe577ab852184335f5b data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_detector.json 19084ac15e80de9255f57ec6f50efe9f287ad47e data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_disk_manipulator.json 6e020575b9eeef96eb31cec01440853d292a78b3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_fluid_grid.json ab76e99e048aa7a507bc2ee71238195f42df1f52 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_grid.json b551e2e756475c031a49169b8cdb7bb1478d5690 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_receiver.json faa57612200a9f95fb0c03bbd00bf3ba07971b10 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_transmitter.json 1b362ecad4b8c539f36bfc93055f0c3396ffbaea data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_pattern_grid.json 2c6093b322f2836d4902537d90fae35df6b2785c data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_relay.json cab4f5742b5bbebd870dc64f4617ac1023b02b2b data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_security_manager.json b3778f099b387d2fa457070572b2b55931c8ee73 data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_wireless_transmitter.json 2c7559a6e8746c6f4b47c006a70b165d181b8c80 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_controller.json 78a4b901f4a3c0a186bbcbe9881bbf9fe0fa4da2 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter.json a5dd747b9b93ea4393fcf401768d1cf521595983 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter_manager.json 584abaeac9f96f87185a65cb221dd5dc94f2e67f data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_grid.json dcb775ecd844a7c9e30d501bef8caa0fc09f5b07 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_monitor.json fb6ae6665e14807c2690f71504c9b26da92142ae data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_detector.json f40b82c9a1bed8dba73353dd8d6104c2744bf5e5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_disk_manipulator.json 577f50cc70ed05e6bb5c1f88cd4f36e6ffdc38a3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_fluid_grid.json 0b295fa3bdc3a126cfb16cdab106eeef65f88077 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_grid.json 1587e589c213f567966fdc5c3009771e51cc83d0 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_receiver.json ed6cf3e3917a03bf1d7d3305297e3d3a5f16f47c data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_transmitter.json ca1ca09f9ea4351c754030e3ca05f7f3a4b45e93 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_pattern_grid.json f5716311b802fd0dbf1c5e56fe7c6936fc35d1fe data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_relay.json 1472f516a95d9e6a7c698acc741c439383eefcbe data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_security_manager.json 83a709b3f2b2d077ece8315b4cd0d414b4d03706 data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_wireless_transmitter.json 193f0653ac14aead77cd82b381bf005527cf710d data/refinedstorage/advancements/recipes/misc/coloring_recipes/relay.json fcb727e6a921c3005c42965f9487ebd1ad5fed72 data/refinedstorage/advancements/recipes/misc/coloring_recipes/security_manager.json dddb4b444133f4c7b25ce0f61a3a99115bf6e34f data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_controller.json 090ff26f519be45f17cd26bbd0a4bffac8788d9f data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter.json 0fab47854d53df7e11046062d079ee2907f45542 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter_manager.json f680b3d58426290b96582ec6c503ed67d70fb76a data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_grid.json ed146018b0984f5b0d1a8268967faaef19137b8c data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_monitor.json efc126ddb87d193a0da48e463b1491c55bc2acd4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_detector.json f5330852a980dc96909fb7d8d0e5fc041f7b7746 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_disk_manipulator.json 5647b0161acd0c3ba7c9be2bb4dbe16a189da2e6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_fluid_grid.json 22e149a387a8f312ba9418a2560a9d90491bbd13 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_grid.json 03d901c37cf4325431dee4b42383821819aeafe5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_receiver.json e972d1fb5200ad4d76e81acca1f0981ffcd3ecd7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_transmitter.json d30354bd77cfe54177d401bac7f3fae3b43a7358 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_pattern_grid.json 885e79474ecd484200a4c74c5b9b5793d3af5f54 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_relay.json 40ebabe8d88e40f05dbd884955e03e6c9874e8fc data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_security_manager.json fe956edaee3a34348d624d99ddd549f40d3643e1 data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_wireless_transmitter.json 6eecfd13553d104c093c3822c148cc7f08d2bd0a data/refinedstorage/advancements/recipes/misc/coloring_recipes/wireless_transmitter.json 6a754b8300dd0e23f9b996cee593916c057ca3d3 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_controller.json 9c632320c99a245a3ecadf9236e6910549e76e54 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter.json adccd41abbcfb9b1bd5deb9f9c1f0ed94fa063ce data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter_manager.json 68e92c065a5f08c8b497c4c383c9430f8cc8e8ba data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_grid.json b5f5f31089375ade9a47c63d3885a83422a1b23b data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_monitor.json 45c6aab891bdd10105893ecfc0f07d0b811083d9 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_detector.json 7c384cda09300a12f85bc22dd004c3e03b6242f5 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_disk_manipulator.json 51916964e73f4ba5bcb2d4f3119b9fb8816753c6 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_fluid_grid.json 659328b91541f94cf9266c43a18dd0f94dc5c415 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_grid.json d29f87c0cf06922d65e8b04de93ab19d29c45001 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_receiver.json d3bb694cf85ff441ba6fa29a6f4c16378a598094 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_transmitter.json b9fee6c5a251fe8294772e0dd0ed3378e79133f8 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_pattern_grid.json 2cfbe64c72ad2fd07d4004a9c099a0c855e621e4 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_relay.json fc362a4803693a183950d7e373153cf802a4ff2b data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_security_manager.json 3b3b450e9af59ba31397fb93c198f57208a243d7 data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_wireless_transmitter.json 9996c185802c040d7454b1cfcfd822605d56b79b data/refinedstorage/advancements/recipes/misc/crafting_grid/black_crafting_grid.json b4a51061a225e0ee4c52af75b79668e2b731b86c data/refinedstorage/advancements/recipes/misc/crafting_grid/blue_crafting_grid.json fc16827a50393291982a6e0e19da4b7e440942f3 data/refinedstorage/advancements/recipes/misc/crafting_grid/brown_crafting_grid.json 05a059a165244eb944688123206078edf380bd35 data/refinedstorage/advancements/recipes/misc/crafting_grid/crafting_grid.json f759470c704e5bf08ddd19d6e0fc738dc22d7256 data/refinedstorage/advancements/recipes/misc/crafting_grid/cyan_crafting_grid.json 9b544ac54835cd3717af3cfa78fc99c626ed857c data/refinedstorage/advancements/recipes/misc/crafting_grid/gray_crafting_grid.json 610cd12ad1fd27af1d428898077a6c1e604dc33f data/refinedstorage/advancements/recipes/misc/crafting_grid/green_crafting_grid.json 5ffe1397bf0f3d666c452303216d3389e4e634c4 data/refinedstorage/advancements/recipes/misc/crafting_grid/light_gray_crafting_grid.json cf48c0c9e45bedfaa2dfc28414ae77b4589bb058 data/refinedstorage/advancements/recipes/misc/crafting_grid/lime_crafting_grid.json 4114ead8379196e77b74d5c91aae72426664944c data/refinedstorage/advancements/recipes/misc/crafting_grid/magenta_crafting_grid.json 323efa415a91a1a57327d2f9f37d85924f59b08b data/refinedstorage/advancements/recipes/misc/crafting_grid/orange_crafting_grid.json b399c6d4a3344a6835d5f869ee2e423369a9a148 data/refinedstorage/advancements/recipes/misc/crafting_grid/pink_crafting_grid.json e99cfcfdb579bca6a1ee5f051f49ddb90e5ff53c data/refinedstorage/advancements/recipes/misc/crafting_grid/purple_crafting_grid.json 81cd4d1b9defdfec2977c5c54fd1d6acdaada81c data/refinedstorage/advancements/recipes/misc/crafting_grid/red_crafting_grid.json 3be49d30bfd65404d73d0a028f8037128ae79f2b data/refinedstorage/advancements/recipes/misc/crafting_grid/white_crafting_grid.json 35df545e58407a3b84abb737ddbc50680da66899 data/refinedstorage/advancements/recipes/misc/crafting_grid/yellow_crafting_grid.json 5705ee4e85e94edf72a96de2dc3fb6ecb60b6729 data/refinedstorage/advancements/recipes/misc/fluid_grid/black_fluid_grid.json e2bf1c90dea3f8e4f67fda2747237da7ba540213 data/refinedstorage/advancements/recipes/misc/fluid_grid/blue_fluid_grid.json 525cfca4916fcc674e741fada4cc606abb745f7c data/refinedstorage/advancements/recipes/misc/fluid_grid/brown_fluid_grid.json ece66d6ed3ee6b031f495034bfa4c38c4a1ae5cc data/refinedstorage/advancements/recipes/misc/fluid_grid/cyan_fluid_grid.json 9e4b7cb2fdfa2805a53cf7dbc496dba36151caed data/refinedstorage/advancements/recipes/misc/fluid_grid/fluid_grid.json 37b3fc51d47c365088514a703cc5fcf11bd6837c data/refinedstorage/advancements/recipes/misc/fluid_grid/gray_fluid_grid.json eaa9e19285209fe2d5bb68953892748b8433cd19 data/refinedstorage/advancements/recipes/misc/fluid_grid/green_fluid_grid.json 2d2a94c20cd953005d4483a0af18af9498006128 data/refinedstorage/advancements/recipes/misc/fluid_grid/light_gray_fluid_grid.json 6217e87d976a2d97f137debe4b7af117bb0d9946 data/refinedstorage/advancements/recipes/misc/fluid_grid/lime_fluid_grid.json c6faf936615279617b893d8a2b8c197f1cdc1922 data/refinedstorage/advancements/recipes/misc/fluid_grid/magenta_fluid_grid.json e1bea619d01e04e61c2295535840a294bda4e46f data/refinedstorage/advancements/recipes/misc/fluid_grid/orange_fluid_grid.json 69f1805039706b422b733e743addcd165452d7eb data/refinedstorage/advancements/recipes/misc/fluid_grid/pink_fluid_grid.json 38d16b36b2c8c1e0dabb778bcf03b967f262739b data/refinedstorage/advancements/recipes/misc/fluid_grid/purple_fluid_grid.json d067044876223011f3e9736673ca67435e9a66e2 data/refinedstorage/advancements/recipes/misc/fluid_grid/red_fluid_grid.json 0d47235aa57900ddca60c8599d92f4a1a79877d0 data/refinedstorage/advancements/recipes/misc/fluid_grid/white_fluid_grid.json 1ffaa363c95cff7d00cad878af9c42015b4bfa1b data/refinedstorage/advancements/recipes/misc/fluid_grid/yellow_fluid_grid.json b4445540f30612fd4ac460c83b20d6adef72c619 data/refinedstorage/advancements/recipes/misc/pattern_grid/black_pattern_grid.json 2aa9e0e19a41b6996a84b9a7ec2416ad0e0f4ab9 data/refinedstorage/advancements/recipes/misc/pattern_grid/blue_pattern_grid.json d75032ae87285c3a4d1924d0655ca50748a40eb7 data/refinedstorage/advancements/recipes/misc/pattern_grid/brown_pattern_grid.json f624f44cf7e80933b2f8351701adfbf2212a8fc5 data/refinedstorage/advancements/recipes/misc/pattern_grid/cyan_pattern_grid.json 03a3dbfb06c413572b93c5426873bddbb32924a2 data/refinedstorage/advancements/recipes/misc/pattern_grid/gray_pattern_grid.json 95614af1e6d8694b29bae065e43e2afce8e252e4 data/refinedstorage/advancements/recipes/misc/pattern_grid/green_pattern_grid.json 905018dec1c9f5224aeb72407967b6983f1f7ed8 data/refinedstorage/advancements/recipes/misc/pattern_grid/light_gray_pattern_grid.json c854b76d5c75b4936394bb331441457aa3a5356f data/refinedstorage/advancements/recipes/misc/pattern_grid/lime_pattern_grid.json 12f393c295bb60814be1bd29ad9e07d5343106fe data/refinedstorage/advancements/recipes/misc/pattern_grid/magenta_pattern_grid.json 1c19ef9067c2ea223a419ce5f6d0967169fe44ea data/refinedstorage/advancements/recipes/misc/pattern_grid/orange_pattern_grid.json e53eb701016f00c8c727a36ccd0d41d6d6ff1cf3 data/refinedstorage/advancements/recipes/misc/pattern_grid/pattern_grid.json caa14b841c970d31a9247387ab7690f17f92f626 data/refinedstorage/advancements/recipes/misc/pattern_grid/pink_pattern_grid.json ce6ed82f788fa0e8fe471971c590b36c5582969a data/refinedstorage/advancements/recipes/misc/pattern_grid/purple_pattern_grid.json 05ed2ae9497d2ff40398d9da5f8c7e2e584536c3 data/refinedstorage/advancements/recipes/misc/pattern_grid/red_pattern_grid.json 82c53eb4b9d9ff5f7ae26b59aafef71c90712006 data/refinedstorage/advancements/recipes/misc/pattern_grid/white_pattern_grid.json 28c917f48693b907454319c6d7f04c56cd9a5e04 data/refinedstorage/advancements/recipes/misc/pattern_grid/yellow_pattern_grid.json 1e484115999fa62d482da0ba86c36e3a7568513c data/refinedstorage/recipes/coloring_recipes/black_controller.json 837df99fec4b00d059e5f258c8c51040989fd59b data/refinedstorage/recipes/coloring_recipes/black_crafter.json cc777c1de15ee96706565e3032d8a17962452316 data/refinedstorage/recipes/coloring_recipes/black_crafter_manager.json 71a7d1ce09686c97292c9f7fe90397a4ee0b3d0e data/refinedstorage/recipes/coloring_recipes/black_crafting_grid.json bf9c9f4ab628826aacb1b310c0997946ed42a023 data/refinedstorage/recipes/coloring_recipes/black_crafting_monitor.json 5c13f67cd1a2c12b948039fef5e5bbe7988e2104 data/refinedstorage/recipes/coloring_recipes/black_detector.json 2ba43fdfa0c9c2e558f5437c63f9629934c1a818 data/refinedstorage/recipes/coloring_recipes/black_disk_manipulator.json 8976bd18990aa165753024ab57e6d4ca0db78e4b data/refinedstorage/recipes/coloring_recipes/black_fluid_grid.json 1931c84a99f99264cfecfa442f0fb7a0f0120aec data/refinedstorage/recipes/coloring_recipes/black_grid.json 7ef51e8c9d67a75733dd35a2147de292476a5b92 data/refinedstorage/recipes/coloring_recipes/black_network_receiver.json 1771e330ab8ed131f3599fbbb384adb0975e998b data/refinedstorage/recipes/coloring_recipes/black_network_transmitter.json 091051a710572811a3667d8e0080c3871bd45daf data/refinedstorage/recipes/coloring_recipes/black_pattern_grid.json fd71581f200ecffd14e85f248329039379222479 data/refinedstorage/recipes/coloring_recipes/black_relay.json e0f4c9cbc082845a2b9b22036600136241594aa7 data/refinedstorage/recipes/coloring_recipes/black_security_manager.json 5e200307f6317b2efa641e2c8616417086d57aac data/refinedstorage/recipes/coloring_recipes/black_wireless_transmitter.json 558cdfb9ab1e1b58165aff5d9cfabc7c18f2ff81 data/refinedstorage/recipes/coloring_recipes/blue_controller.json 877ce0de12f2d1242d436ecc33e7668418afc51c data/refinedstorage/recipes/coloring_recipes/blue_crafter.json c3ecb5dee328da9c2573852eb5f1277c424803e9 data/refinedstorage/recipes/coloring_recipes/blue_crafter_manager.json af1dad13103c12463cc19735b459918785b555a1 data/refinedstorage/recipes/coloring_recipes/blue_crafting_grid.json e1abdfc940501d07568d8e2ff5f4b1305826e907 data/refinedstorage/recipes/coloring_recipes/blue_crafting_monitor.json f82fc0d730557fb523376a6624bba58af1608787 data/refinedstorage/recipes/coloring_recipes/blue_detector.json fa010026eb95b4ae2abe4380c39c412419feeb97 data/refinedstorage/recipes/coloring_recipes/blue_disk_manipulator.json d393aaf88281d449a54345a62db43488f7d9ab35 data/refinedstorage/recipes/coloring_recipes/blue_fluid_grid.json a8f7bda8af1dbbdf0812dca695b352e692d95957 data/refinedstorage/recipes/coloring_recipes/blue_grid.json 9258bde68dc2ca0bc4d1becf182f893cb1427281 data/refinedstorage/recipes/coloring_recipes/blue_network_receiver.json bf71db6ca317ef6cdac9c474869a1506970d759a data/refinedstorage/recipes/coloring_recipes/blue_network_transmitter.json 09e04694c20f5dbf70756431efa00eb10a1e1767 data/refinedstorage/recipes/coloring_recipes/blue_pattern_grid.json c053aa38a5f0bb3b14a3b4d1e835f9db7ad270bb data/refinedstorage/recipes/coloring_recipes/blue_relay.json 2e3eaad4c458805972415b0bb5b6706b98977a19 data/refinedstorage/recipes/coloring_recipes/blue_security_manager.json 3aa1f2ec541238abcd590d042e484cd91041a393 data/refinedstorage/recipes/coloring_recipes/blue_wireless_transmitter.json fe702b3093653416d11cac5c75307b6bf1f523ee data/refinedstorage/recipes/coloring_recipes/brown_controller.json 85f7c531571ce0a8ca574598752a5abf7eb07329 data/refinedstorage/recipes/coloring_recipes/brown_crafter.json 847dc405eb66a48ba1aa44c952f41a0cececcb46 data/refinedstorage/recipes/coloring_recipes/brown_crafter_manager.json 2a0599e860048197e6f09e1ad280733ae4cf6584 data/refinedstorage/recipes/coloring_recipes/brown_crafting_grid.json 41aad04c9677225d7c25aa82737b727bec3f7bc5 data/refinedstorage/recipes/coloring_recipes/brown_crafting_monitor.json c261128142cd85f1cc795f7bd39448af67b3e4de data/refinedstorage/recipes/coloring_recipes/brown_detector.json af05ffb684495cd67a14c42a20bc845a365e1b7c data/refinedstorage/recipes/coloring_recipes/brown_disk_manipulator.json 572f7f49be2f807e698f00f4e4f30bb56ea3aa0b data/refinedstorage/recipes/coloring_recipes/brown_fluid_grid.json ab73cfdade881ba269a8a06397aeb2b82f2a21bd data/refinedstorage/recipes/coloring_recipes/brown_grid.json 85762417f1d46f81d9d74ed1353bd8817dbcde6c data/refinedstorage/recipes/coloring_recipes/brown_network_receiver.json cc4e328b53e6e9d7a064e87b66a3e5cfa6b9fa4f data/refinedstorage/recipes/coloring_recipes/brown_network_transmitter.json f33c81984de9bc038d6c03236fa60dfd52d419a5 data/refinedstorage/recipes/coloring_recipes/brown_pattern_grid.json 210c2b7b92c48d2f32458cc5c3d5910392f9e997 data/refinedstorage/recipes/coloring_recipes/brown_relay.json d895b41ada1d66ab9e7b8632b837f57276d306a7 data/refinedstorage/recipes/coloring_recipes/brown_security_manager.json b60379a43934b84994a7080dcfe007b7a0f3a6ec data/refinedstorage/recipes/coloring_recipes/brown_wireless_transmitter.json ea0e5be25c24c1397a61995e60ad77b0e4957c7b data/refinedstorage/recipes/coloring_recipes/controller.json 0e52aa0f87bd8b55cbe9d2a60d8c3e1e130636f0 data/refinedstorage/recipes/coloring_recipes/crafter.json 5f1a68aeefb616316bf4e30238d59649a731c64a data/refinedstorage/recipes/coloring_recipes/crafter_manager.json b1513edf52ff9f3af93ebf0ca0d305be5d104a41 data/refinedstorage/recipes/coloring_recipes/crafting_grid.json a11298d3883765d7873763e3526ba367c8a46284 data/refinedstorage/recipes/coloring_recipes/crafting_monitor.json 5129a9870a709ff9f4e18855e8b141b760880a72 data/refinedstorage/recipes/coloring_recipes/cyan_controller.json 2c75c39bce50b9759d0ab241cc4a7ebc0ff633b3 data/refinedstorage/recipes/coloring_recipes/cyan_crafter.json c3f47e396862e9aa944348aaf9f254ac50532d11 data/refinedstorage/recipes/coloring_recipes/cyan_crafter_manager.json c1b2a9c366d5062d5c800605b78958f7c34d650f data/refinedstorage/recipes/coloring_recipes/cyan_crafting_grid.json 10b9f12e753b31044f4cb6100f355c88e7fef7f3 data/refinedstorage/recipes/coloring_recipes/cyan_crafting_monitor.json 4d4e1643279662793291a7b24ceb89e44bfcc689 data/refinedstorage/recipes/coloring_recipes/cyan_detector.json 8a1ad5686442737bf11437a1b5a62cff756ccac7 data/refinedstorage/recipes/coloring_recipes/cyan_disk_manipulator.json 4fc265412a18f392c22af9fa4674f9a609e08209 data/refinedstorage/recipes/coloring_recipes/cyan_fluid_grid.json 332fc9c1e21f70e6fe1dda7bb1c964f0ed7715ad data/refinedstorage/recipes/coloring_recipes/cyan_grid.json 819b91726b96bd57eae98d6d8b0b9be99e3db11d data/refinedstorage/recipes/coloring_recipes/cyan_network_receiver.json 7f00009bd87defab006770026bb7a3528a7ce236 data/refinedstorage/recipes/coloring_recipes/cyan_network_transmitter.json 4d77311bce6a5ed341b1e69fa8e808a158e7d767 data/refinedstorage/recipes/coloring_recipes/cyan_pattern_grid.json 0a69efd0b4e23d7225016f731f5e00f176762356 data/refinedstorage/recipes/coloring_recipes/cyan_relay.json 911b3bb449c468e0c45a1fa2eace3649871f80a8 data/refinedstorage/recipes/coloring_recipes/cyan_security_manager.json 545821250a3e514540af53d58c302fd7a53d0964 data/refinedstorage/recipes/coloring_recipes/cyan_wireless_transmitter.json 96fd9b436a78b7a0b40a96768589f609bedb9248 data/refinedstorage/recipes/coloring_recipes/detector.json 0c2555ef2ad11844b1224bcec144f67a109e5449 data/refinedstorage/recipes/coloring_recipes/disk_manipulator.json fd119bae8fc3daee094d892d1197f9ec7152d346 data/refinedstorage/recipes/coloring_recipes/fluid_grid.json 87791b279165a6792585449159085151230b5f50 data/refinedstorage/recipes/coloring_recipes/gray_controller.json 127c027aca2912960a2fef6704eabdb326a60f3b data/refinedstorage/recipes/coloring_recipes/gray_crafter.json 428babaa3af6dbb524c7af06710766f486ad7e93 data/refinedstorage/recipes/coloring_recipes/gray_crafter_manager.json dcee57ab0ba8233854f0db8fe665051d201a5fdd data/refinedstorage/recipes/coloring_recipes/gray_crafting_grid.json 4c499c7feac78f060c224f7da65c24ee57725e9e data/refinedstorage/recipes/coloring_recipes/gray_crafting_monitor.json 372b40564dbb3152f8be6f416a7711b7b65f60cd data/refinedstorage/recipes/coloring_recipes/gray_detector.json c1e9273af3ca3b242e14945fc90a57aea5117f01 data/refinedstorage/recipes/coloring_recipes/gray_disk_manipulator.json 9cecd6f9d03722b87a26f9705db8a253d6f1796d data/refinedstorage/recipes/coloring_recipes/gray_fluid_grid.json aff07f6c78363a60c4c21672ebaecf7cf22ee159 data/refinedstorage/recipes/coloring_recipes/gray_grid.json f0ecd6ccd48024dc2215e73a281ff7a51c8d03c8 data/refinedstorage/recipes/coloring_recipes/gray_network_receiver.json 8e2ee645d974e0c729d1062d91c70bedf6011dfd data/refinedstorage/recipes/coloring_recipes/gray_network_transmitter.json a8adbf5e2f8f4b56a057d070e9888a8c034504f3 data/refinedstorage/recipes/coloring_recipes/gray_pattern_grid.json c9a3e09908a7ea0ab06fe3479147ecad4109f392 data/refinedstorage/recipes/coloring_recipes/gray_relay.json 18c39313de520b58c932425124636d2372e0eb36 data/refinedstorage/recipes/coloring_recipes/gray_security_manager.json 9636a002ade247edd0b2050d26ccb378f04eec9f data/refinedstorage/recipes/coloring_recipes/gray_wireless_transmitter.json 571222e11b04c8c6674d2f16271d3bb58036353d data/refinedstorage/recipes/coloring_recipes/green_controller.json a06ff50f11e287f88c2becff762dfda010752889 data/refinedstorage/recipes/coloring_recipes/green_crafter.json a9ddaf744dcb1157b29604db33cd6bd46a60579f data/refinedstorage/recipes/coloring_recipes/green_crafter_manager.json 5db8a75ccc60e014d9ad80d0610eb15125a55c49 data/refinedstorage/recipes/coloring_recipes/green_crafting_grid.json cd581941ade93fef9c8cbc05a0b52378663ee89c data/refinedstorage/recipes/coloring_recipes/green_crafting_monitor.json d61ba813c27e1eed5e5dd2ace77662bfc60d3ef2 data/refinedstorage/recipes/coloring_recipes/green_detector.json 509a9d12aeba7d2342d7ba2b08b8286d7ac5c356 data/refinedstorage/recipes/coloring_recipes/green_disk_manipulator.json 84d16780e7d8c5eec35b2d0916bbf3ac2558f7d9 data/refinedstorage/recipes/coloring_recipes/green_fluid_grid.json 19e0ac130c216c62826c4505ac0fae1e1ecbde56 data/refinedstorage/recipes/coloring_recipes/green_grid.json 333f3249ffc14e2e69c85a6f4f9d218ae25815f2 data/refinedstorage/recipes/coloring_recipes/green_network_receiver.json a3324bdd1f7f735696680c49e0d03e688ccb2ca0 data/refinedstorage/recipes/coloring_recipes/green_network_transmitter.json e7b213d23d8b95e5d694e4be4eda9ad5b1473e64 data/refinedstorage/recipes/coloring_recipes/green_pattern_grid.json e930e7e251ff813fa59b994a1e9269b5e7dee126 data/refinedstorage/recipes/coloring_recipes/green_relay.json 697124ea286b4ba093101fe9b76fa11da2385b82 data/refinedstorage/recipes/coloring_recipes/green_security_manager.json 8b96cdcfa7cbdb2b89df3ce19e951d7f39be5616 data/refinedstorage/recipes/coloring_recipes/green_wireless_transmitter.json 23e96eb30da11115b605fdca12bf1e05ecdff4de data/refinedstorage/recipes/coloring_recipes/grid.json 5e9675aaef7ddc77b12556cbb9791598a92a07f3 data/refinedstorage/recipes/coloring_recipes/light_gray_controller.json 98fff324cb8b935b7a9516b1eba2fb784b65a3be data/refinedstorage/recipes/coloring_recipes/light_gray_crafter.json b126c981954923e0a320c860cce9ddca6d672f66 data/refinedstorage/recipes/coloring_recipes/light_gray_crafter_manager.json 17cb71c9405814aba06b457d6af6af4d32901859 data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_grid.json 2fb5bc2a239347cc3ae4d6740ac230f04ef4e983 data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_monitor.json 7d22c72c3cec2222329b798d080674403dcdc123 data/refinedstorage/recipes/coloring_recipes/light_gray_detector.json 1b4a0a0deeb2df01e6f73e2ef4a894bd9b060f28 data/refinedstorage/recipes/coloring_recipes/light_gray_disk_manipulator.json b2a284139ae79e1338d89b06452ef8efec0b3e90 data/refinedstorage/recipes/coloring_recipes/light_gray_fluid_grid.json 67373e80a26d1da083b85922524dab408bf53839 data/refinedstorage/recipes/coloring_recipes/light_gray_grid.json bff40091f772b9f2a24fa7e5e2470f6c2c2de55b data/refinedstorage/recipes/coloring_recipes/light_gray_network_receiver.json a1e2bef7f7482107903171d5132cdf12c3ac6ab8 data/refinedstorage/recipes/coloring_recipes/light_gray_network_transmitter.json 4cab0eece82ffdd908f52dd4e1a060fdfa0d308c data/refinedstorage/recipes/coloring_recipes/light_gray_pattern_grid.json 06b1dd6edafe4a8dc03688e65d2540abce6b385f data/refinedstorage/recipes/coloring_recipes/light_gray_relay.json b1042ed6d8ec775933db67d4fec619056d659bba data/refinedstorage/recipes/coloring_recipes/light_gray_security_manager.json 3111fcc735ef720b9bc762606c710f45ffd48400 data/refinedstorage/recipes/coloring_recipes/light_gray_wireless_transmitter.json ae13a92dbc4744a003148eff1d3dcecaa47e0d23 data/refinedstorage/recipes/coloring_recipes/lime_controller.json b5d9f3882743a3ef34d5b25024002824ea96baf2 data/refinedstorage/recipes/coloring_recipes/lime_crafter.json 9896b152c54adc37cdbe7878ad5b6a8c6bdd3121 data/refinedstorage/recipes/coloring_recipes/lime_crafter_manager.json 1db21f1300c4cbb3265c556c6744549383b9a555 data/refinedstorage/recipes/coloring_recipes/lime_crafting_grid.json 0fb2a066450b1de109aa9caba9be689215170c35 data/refinedstorage/recipes/coloring_recipes/lime_crafting_monitor.json c6edccdb599a1cfc0b03bb79ac9b85c809419ec2 data/refinedstorage/recipes/coloring_recipes/lime_detector.json 934dd2b4e0b12f5f5f988d01a3963bde832920be data/refinedstorage/recipes/coloring_recipes/lime_disk_manipulator.json 2b7c26801fd95c0a24d58d0305d6bad8e79090c5 data/refinedstorage/recipes/coloring_recipes/lime_fluid_grid.json 65ef043e374ee6f59f65dbdc88b286da12af3c71 data/refinedstorage/recipes/coloring_recipes/lime_grid.json b0cfb3da8622f05ed21921f924fa51b415b84f38 data/refinedstorage/recipes/coloring_recipes/lime_network_receiver.json efef0d233db0be3a0fe2fffb14388058b7a0dbbf data/refinedstorage/recipes/coloring_recipes/lime_network_transmitter.json 8d1f6f9e387d8b0d83ad97846148a1aafe0d3a5e data/refinedstorage/recipes/coloring_recipes/lime_pattern_grid.json fbf0f28d64c918570d519417f1b1cd65ec368066 data/refinedstorage/recipes/coloring_recipes/lime_relay.json 20bfcb5904525581d2a0c921f3ed18a951629cf5 data/refinedstorage/recipes/coloring_recipes/lime_security_manager.json 80bccc5833f48612764a8c84c30e5abfed586f6f data/refinedstorage/recipes/coloring_recipes/lime_wireless_transmitter.json fb508d9df420507adde445a14bf861f1757cb25c data/refinedstorage/recipes/coloring_recipes/magenta_controller.json 9a09eaaf701c1c109e58a173844a3e4ef4f1c17f data/refinedstorage/recipes/coloring_recipes/magenta_crafter.json e45c83d5bc6d79866d797052d0315368b97b3b7e data/refinedstorage/recipes/coloring_recipes/magenta_crafter_manager.json a149625b63cf3f12a4cf2348c4a1b0b5c6c91bea data/refinedstorage/recipes/coloring_recipes/magenta_crafting_grid.json ca44b8335b9f2b9cae96039e0ff0cda5a2ecfb19 data/refinedstorage/recipes/coloring_recipes/magenta_crafting_monitor.json 826f3b02b1cddf927e6815d28cda43c7c3c6bcd0 data/refinedstorage/recipes/coloring_recipes/magenta_detector.json f4160ad5703892ac81539dfe5d42dfa56a66fb5e data/refinedstorage/recipes/coloring_recipes/magenta_disk_manipulator.json 1677d3ffae4312141d2e0aa0cba00241074172b5 data/refinedstorage/recipes/coloring_recipes/magenta_fluid_grid.json a2c152975047b74488665e2ae2680ca5542a6831 data/refinedstorage/recipes/coloring_recipes/magenta_grid.json 5140b7d4b1035670e5a42744a8c911e22bfb7d8b data/refinedstorage/recipes/coloring_recipes/magenta_network_receiver.json db1ab8b0c13236fb4179d20df1854baafb84698b data/refinedstorage/recipes/coloring_recipes/magenta_network_transmitter.json e75b8d1066fb2d9e3077952993df6a9081603181 data/refinedstorage/recipes/coloring_recipes/magenta_pattern_grid.json 81801f29a3e554e4c4ed98b8b0f71418319f8f8c data/refinedstorage/recipes/coloring_recipes/magenta_relay.json 857f71c7ceaf827efd01ba574c88881e4980e3ef data/refinedstorage/recipes/coloring_recipes/magenta_security_manager.json 369e62e1080765c60d0781de53ab3859c4b665c4 data/refinedstorage/recipes/coloring_recipes/magenta_wireless_transmitter.json e5e382659de78fdab2030e7e5d462e7556c7988a data/refinedstorage/recipes/coloring_recipes/network_receiver.json e0183a74741e0d5768c9336f64a26aafffd46f73 data/refinedstorage/recipes/coloring_recipes/network_transmitter.json 52473cf95f53e31da36cb43f40b6e102840ca392 data/refinedstorage/recipes/coloring_recipes/orange_controller.json 6524d474a295f6852121e19ee55f2a82991d3cb9 data/refinedstorage/recipes/coloring_recipes/orange_crafter.json 670d38ae734ddbd110daed5a621b268084ccc5d9 data/refinedstorage/recipes/coloring_recipes/orange_crafter_manager.json 53d29ecc2217e48f4c8a9f38c5be6eba9876f6ba data/refinedstorage/recipes/coloring_recipes/orange_crafting_grid.json 302a81df05265e4e59b4d84a14e7bb64ba5af729 data/refinedstorage/recipes/coloring_recipes/orange_crafting_monitor.json 9887bc0031479ed703e976e5470e9f0b0fa2af35 data/refinedstorage/recipes/coloring_recipes/orange_detector.json 3a032d126abb017dea46201f92afec58c7850ec5 data/refinedstorage/recipes/coloring_recipes/orange_disk_manipulator.json 8c681ffaa103480ebc523ac1fd957a02ffe0ad6c data/refinedstorage/recipes/coloring_recipes/orange_fluid_grid.json 2531c751e09a4eef9adea51ccb7f251a8df371ab data/refinedstorage/recipes/coloring_recipes/orange_grid.json 0b51e2aaec752b3849c9add94c685fa21ce241c1 data/refinedstorage/recipes/coloring_recipes/orange_network_receiver.json 8cda1a4f63ab5dac7fb1931630f4a36766ace3a0 data/refinedstorage/recipes/coloring_recipes/orange_network_transmitter.json b454a0ce04a16e18d6d1d9b3a82f356c2f5a5a43 data/refinedstorage/recipes/coloring_recipes/orange_pattern_grid.json bc3e05adc7957579b49485cdc44ae48c84fdfce9 data/refinedstorage/recipes/coloring_recipes/orange_relay.json e6d772ca91f90cd3fba8c6c1686f025cdcabebbd data/refinedstorage/recipes/coloring_recipes/orange_security_manager.json 44cf2cc6eecb342b06434db9ee1c9bcc4e5fb096 data/refinedstorage/recipes/coloring_recipes/orange_wireless_transmitter.json 96c9e64ac6b1fda884e583c3dfc578f17523185d data/refinedstorage/recipes/coloring_recipes/pattern_grid.json 44379d03945259c390aeb7bfcc83d2dbbb789cd5 data/refinedstorage/recipes/coloring_recipes/pink_controller.json 7b324217e4253b4c26813ad51bc799e983d73a0e data/refinedstorage/recipes/coloring_recipes/pink_crafter.json cdbca04e29f809d3ad67ff02679a24ba2a4aa07d data/refinedstorage/recipes/coloring_recipes/pink_crafter_manager.json d2c7a7a5eccea5262864f88a4e5154a0d1d8d96b data/refinedstorage/recipes/coloring_recipes/pink_crafting_grid.json 5b8eb35ccf50004142d698fcbe605185a3d72b8a data/refinedstorage/recipes/coloring_recipes/pink_crafting_monitor.json fbc20d7148217e2160e8ffa22059c441c761d720 data/refinedstorage/recipes/coloring_recipes/pink_detector.json a2abdb193c34df50760d3cb1f4c5704ee39b41df data/refinedstorage/recipes/coloring_recipes/pink_disk_manipulator.json 2f2a5446b775976b62915a43f4ff9e21631ebaf9 data/refinedstorage/recipes/coloring_recipes/pink_fluid_grid.json 8f8fde9aece7f5dd15c5579e5686be03085fdb9d data/refinedstorage/recipes/coloring_recipes/pink_grid.json ece30292dfe346d4c25778388932635753380621 data/refinedstorage/recipes/coloring_recipes/pink_network_receiver.json ff5a0d844e0a2390a54a07ac9edeacd2e219592d data/refinedstorage/recipes/coloring_recipes/pink_network_transmitter.json 47dc1079808dd60981c2eab6135fefe6d0c3dc74 data/refinedstorage/recipes/coloring_recipes/pink_pattern_grid.json 3ba8e454038a8a504d5f64954484a735fefe3265 data/refinedstorage/recipes/coloring_recipes/pink_relay.json 6c06e158f115242158aa4f9bef345c22697e6c95 data/refinedstorage/recipes/coloring_recipes/pink_security_manager.json 9b988f2425d07acf55a04cd8310a5ad7dc18370f data/refinedstorage/recipes/coloring_recipes/pink_wireless_transmitter.json 040afa4d28b2bc0a8fba9551c2f9a83a8a55275d data/refinedstorage/recipes/coloring_recipes/purple_controller.json bce4dd6a44a136d2415edec1ac9c53b1c3f51219 data/refinedstorage/recipes/coloring_recipes/purple_crafter.json 98eb23aaa064bd5e4b9099f67218ef11643e68ae data/refinedstorage/recipes/coloring_recipes/purple_crafter_manager.json 12f97e8bcfcc92e85e26365dc23650c4f1790a8c data/refinedstorage/recipes/coloring_recipes/purple_crafting_grid.json 3bb0c59da1362c330c8427933c44a274933bff30 data/refinedstorage/recipes/coloring_recipes/purple_crafting_monitor.json 4ad1ceb85568ac121220d3ad1911d7335b68e783 data/refinedstorage/recipes/coloring_recipes/purple_detector.json 67b741e5a74bba2d24dc22f3b9c59ed8e9ab8ee2 data/refinedstorage/recipes/coloring_recipes/purple_disk_manipulator.json 0bcbdf519eabf09e3818588558b3e9ce7d6fceb3 data/refinedstorage/recipes/coloring_recipes/purple_fluid_grid.json 4eefec69f667cf88eb3a1e651fd2beba93870597 data/refinedstorage/recipes/coloring_recipes/purple_grid.json 8a5e04a5d6130b299bacf95a62fab5f8e707877b data/refinedstorage/recipes/coloring_recipes/purple_network_receiver.json 4f2e6f74509c70d312b71632f4c38be3cfeba77c data/refinedstorage/recipes/coloring_recipes/purple_network_transmitter.json 7309f883662ccbbaa97fa3cdb479674c2cdc7516 data/refinedstorage/recipes/coloring_recipes/purple_pattern_grid.json ea8f6b5d26335c64f511f8d854a6f18c944acdcb data/refinedstorage/recipes/coloring_recipes/purple_relay.json 661e9d811201abfb56b7b27175b9ec1e10de1584 data/refinedstorage/recipes/coloring_recipes/purple_security_manager.json 384938122caeca74c92e8047e386244db2e19985 data/refinedstorage/recipes/coloring_recipes/purple_wireless_transmitter.json 5213d1fc2c6269321b78a23eafc533968677631e data/refinedstorage/recipes/coloring_recipes/red_controller.json 8d9ca91c28c9ca40c932688bccb88261f6c6402c data/refinedstorage/recipes/coloring_recipes/red_crafter.json 98b6fb4a2141356fb7e18995288935d5b0617c4e data/refinedstorage/recipes/coloring_recipes/red_crafter_manager.json e424d6daf7fdfa9f62c920b8f551dafb6907ea9c data/refinedstorage/recipes/coloring_recipes/red_crafting_grid.json 0160755468a19e98b4dbc4447b1efae7dec53e0f data/refinedstorage/recipes/coloring_recipes/red_crafting_monitor.json 1a9cbbb583120ee079d3191bbf399651cd89577a data/refinedstorage/recipes/coloring_recipes/red_detector.json 29148381c6707e3b7181d534255baee78917ac95 data/refinedstorage/recipes/coloring_recipes/red_disk_manipulator.json 4d63aa706daf331f47978f66e0fd3dc29ae223ac data/refinedstorage/recipes/coloring_recipes/red_fluid_grid.json c8be1ebdf463794c8aeb52003d035ebac78be94d data/refinedstorage/recipes/coloring_recipes/red_grid.json 4a3d94a64b099bd47c84e15b3fabba7fc985f065 data/refinedstorage/recipes/coloring_recipes/red_network_receiver.json dc1c971e5d0f8874c294b975309ea8f01ea51e5e data/refinedstorage/recipes/coloring_recipes/red_network_transmitter.json ee5aeaeb62cef55b5538018706a83d624748ef00 data/refinedstorage/recipes/coloring_recipes/red_pattern_grid.json 9dc5bda9e6a365c83a50b039935603ef7c977938 data/refinedstorage/recipes/coloring_recipes/red_relay.json 35215d8666e19b9c91e32b20d461f2b098f5f734 data/refinedstorage/recipes/coloring_recipes/red_security_manager.json dd2d8f572913d26f79cfee38a679fec72ba27a40 data/refinedstorage/recipes/coloring_recipes/red_wireless_transmitter.json 1bfa44597a6301d570a09ac73be6bca9da6f9483 data/refinedstorage/recipes/coloring_recipes/relay.json 83f1a7f20933935059cf86c44b4194718c3cff1d data/refinedstorage/recipes/coloring_recipes/security_manager.json b42095cd9222c36d358a578f48af359a0bfdf026 data/refinedstorage/recipes/coloring_recipes/white_controller.json c8b886a2890b64e3f746ae55f3dcc9c526fc390d data/refinedstorage/recipes/coloring_recipes/white_crafter.json 1564dc43ec03da2e6bf11e7ee9a73a65a3506690 data/refinedstorage/recipes/coloring_recipes/white_crafter_manager.json 0efeb724bf6b11cb03f91f1c1de6dfe0f7731704 data/refinedstorage/recipes/coloring_recipes/white_crafting_grid.json 4ed50e1f8369240d1f87e9be9190ad7244b2e996 data/refinedstorage/recipes/coloring_recipes/white_crafting_monitor.json b8123ca500d032d5cf14fa4eb6acf94819735c8f data/refinedstorage/recipes/coloring_recipes/white_detector.json 27bdf73bccced8c2f694be1327f6e59d38e667fe data/refinedstorage/recipes/coloring_recipes/white_disk_manipulator.json 37681dbb38a2cae990001cadda98107f7a85d8ba data/refinedstorage/recipes/coloring_recipes/white_fluid_grid.json 746481e67dc39802296560c6286a1896162f656e data/refinedstorage/recipes/coloring_recipes/white_grid.json d3fabfda138031705c70e6f558e89a80b6304f7f data/refinedstorage/recipes/coloring_recipes/white_network_receiver.json f0e6c4760dd916b3f27c67d9d372a12d7438eefd data/refinedstorage/recipes/coloring_recipes/white_network_transmitter.json 88d61adc326d663112475ea2eeafc39e2c00dfb1 data/refinedstorage/recipes/coloring_recipes/white_pattern_grid.json fc289082d30d79a6901963f169c96cc9bb13c2db data/refinedstorage/recipes/coloring_recipes/white_relay.json 6a813bd5fe61dfa8f8843c0a41eb63c8a179d24c data/refinedstorage/recipes/coloring_recipes/white_security_manager.json d10924039deb155dbe8626c1a122f7a4a2b5a1ba data/refinedstorage/recipes/coloring_recipes/white_wireless_transmitter.json de06ff58be01086d2db6708903219a6d30e54dbd data/refinedstorage/recipes/coloring_recipes/wireless_transmitter.json 5ab08310c1bca2d1e6fc97f1611db8dce66b01d3 data/refinedstorage/recipes/coloring_recipes/yellow_controller.json d988c6e9533eb8e93ec8b219b5d032596d89ae8d data/refinedstorage/recipes/coloring_recipes/yellow_crafter.json 79cfee17ee03565aa0a27ada8d9f375b4cb665bc data/refinedstorage/recipes/coloring_recipes/yellow_crafter_manager.json 8a4c6b78bb4fef3ceef338ac655c80503190059d data/refinedstorage/recipes/coloring_recipes/yellow_crafting_grid.json a1b1f47a605beccad8acacfbaf77964e991f0a4f data/refinedstorage/recipes/coloring_recipes/yellow_crafting_monitor.json 10f0ea9ac167aee81a610da0c4b16465be3c39e0 data/refinedstorage/recipes/coloring_recipes/yellow_detector.json 335a728979bc32d15ed7d72a84e3eddfa9c55b95 data/refinedstorage/recipes/coloring_recipes/yellow_disk_manipulator.json 0393b2ce55a6202b4eee5ce0b2d3344ab2b8e11b data/refinedstorage/recipes/coloring_recipes/yellow_fluid_grid.json 9cef292a0457b7987442d04572047f286bc20fc0 data/refinedstorage/recipes/coloring_recipes/yellow_grid.json 63c20b0f45f8453a2588da8e0f915de07d91073f data/refinedstorage/recipes/coloring_recipes/yellow_network_receiver.json 0c0e1fc0dd6d4251b655e3c3232ab393f380722c data/refinedstorage/recipes/coloring_recipes/yellow_network_transmitter.json d66efb72494084b29a32b81c1f72bc5b37088689 data/refinedstorage/recipes/coloring_recipes/yellow_pattern_grid.json 513f415c4ba145ab71bfa892a04ddb02cfaa80c8 data/refinedstorage/recipes/coloring_recipes/yellow_relay.json 656ab81fea0782a64a0b129f50095cbcff47dc41 data/refinedstorage/recipes/coloring_recipes/yellow_security_manager.json 7fc4f29327366fb10065e0fad63df119c706d55e data/refinedstorage/recipes/coloring_recipes/yellow_wireless_transmitter.json bc35cb59ff004ffc78886d46608b3c81072bfdbd data/refinedstorage/recipes/crafting_grid/black_crafting_grid.json 97f1bd4e344764dbdefd260fb35c749d4b7fdb21 data/refinedstorage/recipes/crafting_grid/blue_crafting_grid.json 867de3ece15a35979d7ed3e0d1a10c581a825ab7 data/refinedstorage/recipes/crafting_grid/brown_crafting_grid.json 0f17bd970606073347d35401d2fe7bbf66033052 data/refinedstorage/recipes/crafting_grid/crafting_grid.json 41fe7509aa8bfa0dba6e26641ee318c89b4f583a data/refinedstorage/recipes/crafting_grid/cyan_crafting_grid.json 16256265f3c2a6ad33fc3dde40c588f94de97cbb data/refinedstorage/recipes/crafting_grid/gray_crafting_grid.json 554f972cfa470f77b2ed03e3c580a489d981200e data/refinedstorage/recipes/crafting_grid/green_crafting_grid.json 246bd2536f0109a299f4d8f46e820dbaa94f8f83 data/refinedstorage/recipes/crafting_grid/light_gray_crafting_grid.json f8264879f798b5977e2fa8598b7b70895f18bc77 data/refinedstorage/recipes/crafting_grid/lime_crafting_grid.json 2e50e2eb39657b2dbe7a804ac8fc520f5f90d2cb data/refinedstorage/recipes/crafting_grid/magenta_crafting_grid.json a4b7575e6a11a3717c1a72cff0273c621b6f3a0d data/refinedstorage/recipes/crafting_grid/orange_crafting_grid.json 580d7623cbe6b53a1f0d84dcd5fdfd77716251e1 data/refinedstorage/recipes/crafting_grid/pink_crafting_grid.json 806d5168ce1cc39a8fd39e0eda55de1f4ab20484 data/refinedstorage/recipes/crafting_grid/purple_crafting_grid.json defa112e99475c51d55edabbbc54a8ae26e32257 data/refinedstorage/recipes/crafting_grid/red_crafting_grid.json b4d1347ed742afbde81c5b14c132a21eaf9ca884 data/refinedstorage/recipes/crafting_grid/white_crafting_grid.json c9a5db4ebcd1924d32787987fed38a164acb360f data/refinedstorage/recipes/crafting_grid/yellow_crafting_grid.json 06566cbfe62a2783dab30391f8353175214a2071 data/refinedstorage/recipes/fluid_grid/black_fluid_grid.json dba62f4ae40b27bdf17803904fab31d8e3c1b481 data/refinedstorage/recipes/fluid_grid/blue_fluid_grid.json 84c68d2bcc4831e93d3da768e49ce193474193c3 data/refinedstorage/recipes/fluid_grid/brown_fluid_grid.json 81db210076da3b665841bd4eb17ce80c881aa782 data/refinedstorage/recipes/fluid_grid/cyan_fluid_grid.json 3f27e8e601206031c607f74ffb8bfa27434c4eea data/refinedstorage/recipes/fluid_grid/fluid_grid.json 772ec2b3e75670f3f574fd1f9a0a50229df71c23 data/refinedstorage/recipes/fluid_grid/gray_fluid_grid.json c1c3ca490a74e17f20ff413d8300f5bf4dadce28 data/refinedstorage/recipes/fluid_grid/green_fluid_grid.json 7e5ac70a9cad754664b18caba3995c2df2edafbc data/refinedstorage/recipes/fluid_grid/light_gray_fluid_grid.json 4eb90edc1dd25cd99eb7f171afd84d647e9f3a5d data/refinedstorage/recipes/fluid_grid/lime_fluid_grid.json 12993cc922c42d66ea486143178bde12814d6f72 data/refinedstorage/recipes/fluid_grid/magenta_fluid_grid.json ad42253972dde97319fc963cca9f276cd682a434 data/refinedstorage/recipes/fluid_grid/orange_fluid_grid.json 42fa4ba965eb143060edc58fd354fd166d7d7ee3 data/refinedstorage/recipes/fluid_grid/pink_fluid_grid.json a3cd500967a7ca8bbdc63b5f7e28cda83332f764 data/refinedstorage/recipes/fluid_grid/purple_fluid_grid.json acc3d1c9823a56f4fcd3ed4a10800017b3470308 data/refinedstorage/recipes/fluid_grid/red_fluid_grid.json f82ad46f703166947701746f367fb3e9c9ee13e6 data/refinedstorage/recipes/fluid_grid/white_fluid_grid.json 0493642eb294a1ddd03aea909e9412c6e7d7cb13 data/refinedstorage/recipes/fluid_grid/yellow_fluid_grid.json cf865a91fe46c1a6d177eba5bd659d7306e4b752 data/refinedstorage/recipes/pattern_grid/black_pattern_grid.json 595c344e5a3ee10eedbb3911adb7d1637d2d25c5 data/refinedstorage/recipes/pattern_grid/blue_pattern_grid.json 78ce90102d193d4d1dac5c93a1aef10188e63258 data/refinedstorage/recipes/pattern_grid/brown_pattern_grid.json 77f667c9bb96f33e8d753b54bf770b63fca33e7c data/refinedstorage/recipes/pattern_grid/cyan_pattern_grid.json fc5e7f25f6a72af1623604cfa64a978f5ccffeec data/refinedstorage/recipes/pattern_grid/gray_pattern_grid.json dc03f0e09c3b4ab00ef3ee40c7cc09ec9b82e30e data/refinedstorage/recipes/pattern_grid/green_pattern_grid.json 7ea662fadd5ab396382788cce9b9f3b46a454f29 data/refinedstorage/recipes/pattern_grid/light_gray_pattern_grid.json e7affc6561b15e1ae04bce3daa9824fe137bf909 data/refinedstorage/recipes/pattern_grid/lime_pattern_grid.json 65f0ef8dfae6e58433b9c59def75afaf5c0b632c data/refinedstorage/recipes/pattern_grid/magenta_pattern_grid.json 37dcf0cd09c15ece8123456213b0d510d754ab22 data/refinedstorage/recipes/pattern_grid/orange_pattern_grid.json bda3a866c990f55409a0ff0d5643184d73e23961 data/refinedstorage/recipes/pattern_grid/pattern_grid.json cfbc0ab0d39fca6ddc432c497427019bb7e70dad data/refinedstorage/recipes/pattern_grid/pink_pattern_grid.json a9d41d0fd2a9eb83673ce0c4015d40a249f9afa5 data/refinedstorage/recipes/pattern_grid/purple_pattern_grid.json 151b980298e4968ef4227cc62a351cd2c17c2331 data/refinedstorage/recipes/pattern_grid/red_pattern_grid.json ef55bc909cc5ac605db1a673a310942549072eab data/refinedstorage/recipes/pattern_grid/white_pattern_grid.json abd03dded7af5ea3d4d05f192496760d1a07470a data/refinedstorage/recipes/pattern_grid/yellow_pattern_grid.json ================================================ FILE: src/generated/resources/.cache/c52895b732924e707cb6e5ddd1c6b6962039449c ================================================ // 1.20.4 2024-02-12T20:34:18.531158825 Block Entity Type Tags 98555d946827da8ddb7a7c451a1c99f4d0184ad3 data/packingtape/tags/block_entity_type/blacklist/problematic.json ================================================ FILE: src/generated/resources/.cache/cb654f100e416ac39358630d6623170b9bfdc5d2 ================================================ // 1.20.4 2024-02-12T20:34:18.533198729 Tags for minecraft:item mod id refinedstorage 061bf4c2f3bdd530115615f2b04e55c2602908bd data/refinedstorage/tags/items/controller.json 407a16e5d941c69915f75b135a13e9144cc9c43e data/refinedstorage/tags/items/crafter.json dc1342f1d3e6a4cd8eaaa52429a011c10c6c2d96 data/refinedstorage/tags/items/crafter_manager.json 2f8fee222ac543909ae06a35de3c08e3e19f4f4b data/refinedstorage/tags/items/crafting_grid.json bf4f4ed5b02babe4717894e4823d5541d69dbfe6 data/refinedstorage/tags/items/crafting_monitor.json 6abdee7222576fd0b2da7f86954e35ca8cab4d25 data/refinedstorage/tags/items/detector.json 7b9c6d4ef32d5e63c327d71a8758f8b900ac9cb6 data/refinedstorage/tags/items/disk_manipulator.json 651ca3794c0a1c28aa275a9814de7fdc04c90653 data/refinedstorage/tags/items/fluid_grid.json 31a65b9d23f79a0191f78ba46c5ed39942d38023 data/refinedstorage/tags/items/grid.json 295fce6281b688f4992b1181c58e9a52c80465a1 data/refinedstorage/tags/items/network_receiver.json 37ea6fd2ffdb762fb9351359ddf9cc0f401bbbf5 data/refinedstorage/tags/items/network_transmitter.json 9dae822d3373a348a6ab4e11de2056f369a0253b data/refinedstorage/tags/items/pattern_grid.json 52c8060208bf763f487313b8de6243550cc2f63a data/refinedstorage/tags/items/relay.json 555b5c80da6838aa2a4d8f5044276852b1bc525d data/refinedstorage/tags/items/security_manager.json e740b41d26fe5be1b6251db461627b8e5e5925aa data/refinedstorage/tags/items/wireless_transmitter.json ================================================ FILE: src/generated/resources/.cache/f481442ce31db2c3b3dabb5b6d85f9a78568164e ================================================ // 1.20.4 2024-02-12T20:34:18.553572165 Tags for minecraft:block mod id refinedstorage 7af8948adf9214476b9b2995799c32277c960c55 data/forge/tags/blocks/relocation_not_supported.json 061bf4c2f3bdd530115615f2b04e55c2602908bd data/refinedstorage/tags/blocks/controller.json 407a16e5d941c69915f75b135a13e9144cc9c43e data/refinedstorage/tags/blocks/crafter.json dc1342f1d3e6a4cd8eaaa52429a011c10c6c2d96 data/refinedstorage/tags/blocks/crafter_manager.json 2f8fee222ac543909ae06a35de3c08e3e19f4f4b data/refinedstorage/tags/blocks/crafting_grid.json bf4f4ed5b02babe4717894e4823d5541d69dbfe6 data/refinedstorage/tags/blocks/crafting_monitor.json 4c7059780d3896d0f042e88076b8a0326e0cf86d data/refinedstorage/tags/blocks/creative_controller.json 6abdee7222576fd0b2da7f86954e35ca8cab4d25 data/refinedstorage/tags/blocks/detector.json 7b9c6d4ef32d5e63c327d71a8758f8b900ac9cb6 data/refinedstorage/tags/blocks/disk_manipulator.json 651ca3794c0a1c28aa275a9814de7fdc04c90653 data/refinedstorage/tags/blocks/fluid_grid.json 31a65b9d23f79a0191f78ba46c5ed39942d38023 data/refinedstorage/tags/blocks/grid.json 295fce6281b688f4992b1181c58e9a52c80465a1 data/refinedstorage/tags/blocks/network_receiver.json 37ea6fd2ffdb762fb9351359ddf9cc0f401bbbf5 data/refinedstorage/tags/blocks/network_transmitter.json 9dae822d3373a348a6ab4e11de2056f369a0253b data/refinedstorage/tags/blocks/pattern_grid.json 52c8060208bf763f487313b8de6243550cc2f63a data/refinedstorage/tags/blocks/relay.json 555b5c80da6838aa2a4d8f5044276852b1bc525d data/refinedstorage/tags/blocks/security_manager.json e740b41d26fe5be1b6251db461627b8e5e5925aa data/refinedstorage/tags/blocks/wireless_transmitter.json ================================================ FILE: src/generated/resources/.cache/fd27170b6bf91459ed2598d25721edfeafc82e0a ================================================ // 1.20.4 2024-02-12T20:34:18.545348794 Block States: refinedstorage 7b69e3ab3a7471a50e264579d36c04adb8acad35 assets/refinedstorage/blockstates/black_controller.json c87045bd089212825bdd0f06b0d25e7bcf0e3f5d assets/refinedstorage/blockstates/black_crafter.json 999fe91e1661d6b45f9c29878f06438b3b5919dc assets/refinedstorage/blockstates/black_crafter_manager.json 6dfbf26cac2596445fce1b6bae6df2e3b161100a assets/refinedstorage/blockstates/black_crafting_grid.json cad10d852489b5c9f7bc570d658bc2d3503da7d7 assets/refinedstorage/blockstates/black_crafting_monitor.json 7b69e3ab3a7471a50e264579d36c04adb8acad35 assets/refinedstorage/blockstates/black_creative_controller.json 16e7f975097055171aa436c1a632715a9ef8341a assets/refinedstorage/blockstates/black_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/black_disk_manipulator.json 2d65d70d315150a429448eae15cd20045596d27b assets/refinedstorage/blockstates/black_fluid_grid.json 2a89227c1e5c69cf378001ec5c804e8057b94925 assets/refinedstorage/blockstates/black_grid.json fb8aa2633b61db8bc3c6a0e4baac65089c48fc43 assets/refinedstorage/blockstates/black_network_receiver.json 05ffd20caf7ca4db1806b9d0872b32804966368d assets/refinedstorage/blockstates/black_network_transmitter.json 728791ad72200b43e0e873405aff863faaa0d667 assets/refinedstorage/blockstates/black_pattern_grid.json 808e7192637fba2b5dff521b0b8830f9f62ca819 assets/refinedstorage/blockstates/black_relay.json e5c9aaad492c8643c7e82b9b8cdaa3bcbd1068e6 assets/refinedstorage/blockstates/black_security_manager.json d749ab3e2d6aae2c4ac4610850791d4e0ba31b72 assets/refinedstorage/blockstates/black_wireless_transmitter.json c259424f1ef73c4dc12d770ba1c47fcf965e6175 assets/refinedstorage/blockstates/blue_controller.json 0b1e46e3502ef5dc39129f01e77423842f378523 assets/refinedstorage/blockstates/blue_crafter.json 667d3a36aa89313f5ded585f8ada125a0380ea61 assets/refinedstorage/blockstates/blue_crafter_manager.json 32a82613e09f6c5dc5dfa9ee6b0b7901518af5f4 assets/refinedstorage/blockstates/blue_crafting_grid.json 274b86b9b6df510a58e65ca7b80529d1ba88c699 assets/refinedstorage/blockstates/blue_crafting_monitor.json c259424f1ef73c4dc12d770ba1c47fcf965e6175 assets/refinedstorage/blockstates/blue_creative_controller.json d71686564d14b615681df9140c6b4d6d948673cd assets/refinedstorage/blockstates/blue_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/blue_disk_manipulator.json 3822722dbfebcac426e9d07a8fbad76a3c72f106 assets/refinedstorage/blockstates/blue_fluid_grid.json 031ee9de046949535200ccf5e1a5e9439adbb282 assets/refinedstorage/blockstates/blue_grid.json 9ccd5c6695f09476c0a6c1af1728809efea90054 assets/refinedstorage/blockstates/blue_network_receiver.json b20dd47441068c7b8ed38c4ed4c857f6e0ec0b0b assets/refinedstorage/blockstates/blue_network_transmitter.json a9fb566f3c1f6779ef2b03ec847d6736beab92cd assets/refinedstorage/blockstates/blue_pattern_grid.json 3fae9d1e68030dbcbbaeb4534a39e915b1c8f976 assets/refinedstorage/blockstates/blue_relay.json 69dac9e3833cd351672467aa34e19f2bf466cfe7 assets/refinedstorage/blockstates/blue_security_manager.json 4566b01a555b7307bf1ea8390def853089a69d49 assets/refinedstorage/blockstates/blue_wireless_transmitter.json b78e4501f02364499a0aeaf599eb32fc010f1c58 assets/refinedstorage/blockstates/brown_controller.json 965abf8e749ac0cf7b585946dfa5ea5898fdc9d9 assets/refinedstorage/blockstates/brown_crafter.json 27b1077b0aa443abadd855ff340e10504ae6faec assets/refinedstorage/blockstates/brown_crafter_manager.json d01e8708c28a9aeb6658510d7aa767294607dc97 assets/refinedstorage/blockstates/brown_crafting_grid.json 94e4f8e400897059d52362997170ffcae2291340 assets/refinedstorage/blockstates/brown_crafting_monitor.json b78e4501f02364499a0aeaf599eb32fc010f1c58 assets/refinedstorage/blockstates/brown_creative_controller.json caa950648cde215f3110c9530a3916c38a578f61 assets/refinedstorage/blockstates/brown_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/brown_disk_manipulator.json ecf5814b4e50a7ef37e3bbcc383ea0540ff34bc8 assets/refinedstorage/blockstates/brown_fluid_grid.json f67203e2d420ee9b164432a6c631c1045c0839f3 assets/refinedstorage/blockstates/brown_grid.json a8af2cefa692c0485a61fd932cb9dbf3336a94b7 assets/refinedstorage/blockstates/brown_network_receiver.json b26700458e89654d8c180da1997f309532366ae0 assets/refinedstorage/blockstates/brown_network_transmitter.json 1953b72641278b83ab9102612d21e8308dacc1ab assets/refinedstorage/blockstates/brown_pattern_grid.json 449f908d91689f0750bfa9ea15212cdf884f8d37 assets/refinedstorage/blockstates/brown_relay.json b2bc3d1c93df4307a16eb3df245418318ba08b0f assets/refinedstorage/blockstates/brown_security_manager.json 3ef998a83b2388ba0133c6d5fe9d3d96ee9823b5 assets/refinedstorage/blockstates/brown_wireless_transmitter.json 6bebb7848ef81448082cb992878e5468cda66d3b assets/refinedstorage/blockstates/controller.json 66a78b99df31444ee80aaf5790fdf29a5fb97c67 assets/refinedstorage/blockstates/crafter.json 711443d364ea85b23bd61902e4cfec0897175b36 assets/refinedstorage/blockstates/crafter_manager.json 9fdd6f844061b5d7eb5dc141f9a087a33e7297cd assets/refinedstorage/blockstates/crafting_grid.json c0f0ae43414371d80a42639792bb8845da5f06b7 assets/refinedstorage/blockstates/crafting_monitor.json 6bebb7848ef81448082cb992878e5468cda66d3b assets/refinedstorage/blockstates/creative_controller.json 32ed126a06d3cfadeaffdb5f72a92d0992841bf1 assets/refinedstorage/blockstates/cyan_controller.json 90b9eb7f6ca9f3b3d0c6db53553abfc74236e9fe assets/refinedstorage/blockstates/cyan_crafter.json c07193099f8241889ef04dae18a2a57ab31f0e64 assets/refinedstorage/blockstates/cyan_crafter_manager.json e25b53ada26df3ac55b532b0e5a8b7d1378f8f6e assets/refinedstorage/blockstates/cyan_crafting_grid.json 70a431cfe0a7b6049ad2c4d8da449b523151db70 assets/refinedstorage/blockstates/cyan_crafting_monitor.json 32ed126a06d3cfadeaffdb5f72a92d0992841bf1 assets/refinedstorage/blockstates/cyan_creative_controller.json d39cb51f414057d970a458dfea5c191ec7ba06b0 assets/refinedstorage/blockstates/cyan_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/cyan_disk_manipulator.json 0b59eab2a3214c33ea7fdd50198e4f3943ea9cdb assets/refinedstorage/blockstates/cyan_fluid_grid.json e2c86885cf2995be56fdc0728e9e900021583cd5 assets/refinedstorage/blockstates/cyan_grid.json 349ef6721ac006319818a900a9f2fef402b9c1c1 assets/refinedstorage/blockstates/cyan_network_receiver.json 02875332d7cc05994f93f7d08d7f33f5f4692575 assets/refinedstorage/blockstates/cyan_network_transmitter.json b0452599b5e58599d488d497f1d64f2086d8f045 assets/refinedstorage/blockstates/cyan_pattern_grid.json f03e4611123ae67fb17aadc4ea23c00b94724e06 assets/refinedstorage/blockstates/cyan_relay.json bf496398c00ca9e5421afa96a3c309b2b9a09b78 assets/refinedstorage/blockstates/cyan_security_manager.json 9cc1f2365298c5d92edc078988c162ca12ee1b58 assets/refinedstorage/blockstates/cyan_wireless_transmitter.json 54c8d36899d719e379d0f45c48aae5938711825c assets/refinedstorage/blockstates/detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/disk_manipulator.json dad2436c0b678d06dc5568506c83f8acc3227e09 assets/refinedstorage/blockstates/fluid_grid.json bbadd742d5662d38447d6d8242c074816e227242 assets/refinedstorage/blockstates/gray_controller.json 547ef6ae4c9797e02bc0ebe3c6f51c9959bd7a0b assets/refinedstorage/blockstates/gray_crafter.json 45995d7e5902cf8f93c679df972915d6af8970a9 assets/refinedstorage/blockstates/gray_crafter_manager.json 5bc03e1cb45ffa4e68813dfdb6a08c83275d519a assets/refinedstorage/blockstates/gray_crafting_grid.json 3e50d6bc784f38230a670ca079c48a9313047b00 assets/refinedstorage/blockstates/gray_crafting_monitor.json bbadd742d5662d38447d6d8242c074816e227242 assets/refinedstorage/blockstates/gray_creative_controller.json aa366bb135b9ea8f5015a16d31bb044634186baa assets/refinedstorage/blockstates/gray_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/gray_disk_manipulator.json 67fee64c36afe0e98dc75921c7a3f59d712fb194 assets/refinedstorage/blockstates/gray_fluid_grid.json 19e248101a9be45e302512a47bd047da7799474f assets/refinedstorage/blockstates/gray_grid.json f7f6f6c790e006776bf86b69646d1ff40e77b077 assets/refinedstorage/blockstates/gray_network_receiver.json 82e103363281a88aeec3677838c92835f2377b89 assets/refinedstorage/blockstates/gray_network_transmitter.json 80604de4035aca7788b911888d33d1c4d73c73e6 assets/refinedstorage/blockstates/gray_pattern_grid.json d3b748f6d6499cb1d25b75f0416672007e2c8427 assets/refinedstorage/blockstates/gray_relay.json fde90f14de4329db7c8acff70e03d5807435af90 assets/refinedstorage/blockstates/gray_security_manager.json 66c222b50b4bca71aa058b708259efd7b4a5515d assets/refinedstorage/blockstates/gray_wireless_transmitter.json eaedbfdf6c84624f585530b187613d35da49220e assets/refinedstorage/blockstates/green_controller.json 40a39c28577f7c8754ccef601cf271d36c013c75 assets/refinedstorage/blockstates/green_crafter.json 12414cdabaf1ea9c9a48afce88f0535ac63218a1 assets/refinedstorage/blockstates/green_crafter_manager.json 118ccfc4cb3ba98ade2f85771b8fa7850a8b39d5 assets/refinedstorage/blockstates/green_crafting_grid.json a9391e55df0b63c7223e21c71f867c19ec87091a assets/refinedstorage/blockstates/green_crafting_monitor.json eaedbfdf6c84624f585530b187613d35da49220e assets/refinedstorage/blockstates/green_creative_controller.json 671bdde024f725835b8d7c70294666d67d013905 assets/refinedstorage/blockstates/green_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/green_disk_manipulator.json 9ae0a3edbd87718686e42978e70725e170cd2e3a assets/refinedstorage/blockstates/green_fluid_grid.json 5d5a7cdf0fafae953b3a6d7bc0773eafd0bb36d1 assets/refinedstorage/blockstates/green_grid.json 1f68b48cce41bb6bef4c1499b4cf82873f3f4d23 assets/refinedstorage/blockstates/green_network_receiver.json ad9ae867a12847c3a33451c315459660133f988e assets/refinedstorage/blockstates/green_network_transmitter.json cb26162f351bf30aed31b993851156334371beac assets/refinedstorage/blockstates/green_pattern_grid.json 2df12e30a33dfe832a61465727cedc1ce9d4a808 assets/refinedstorage/blockstates/green_relay.json c9bfb5d4002df591d9ac35054e719340799e7f52 assets/refinedstorage/blockstates/green_security_manager.json 53d5e92bf89fdf857816ebc8af61763c5aca0fa1 assets/refinedstorage/blockstates/green_wireless_transmitter.json b3389b5e12d6bf8f1a4aab9281b5c3dee442da75 assets/refinedstorage/blockstates/grid.json 47f2adbd7d2a25cd564556f44b028459306d17d9 assets/refinedstorage/blockstates/light_gray_controller.json 9947ef84be868d3d911e386c09519db9eb5a87f5 assets/refinedstorage/blockstates/light_gray_crafter.json 0f66d91089d5e55e652ce8b7aee06bb0710bf2c3 assets/refinedstorage/blockstates/light_gray_crafter_manager.json 62f1453961eb0aa4bde17417a6d74759489c7db6 assets/refinedstorage/blockstates/light_gray_crafting_grid.json 4f49c3a2ed3fb80739efaa40c590bacee28ccd18 assets/refinedstorage/blockstates/light_gray_crafting_monitor.json 47f2adbd7d2a25cd564556f44b028459306d17d9 assets/refinedstorage/blockstates/light_gray_creative_controller.json 29d62af6861ef704d341f156e2b8ba422d2bc815 assets/refinedstorage/blockstates/light_gray_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/light_gray_disk_manipulator.json 0b83619570c7fd6276e63db434ab586964001e49 assets/refinedstorage/blockstates/light_gray_fluid_grid.json 58c51e122a1a6dc3ae49236e51b5ced8dd65f025 assets/refinedstorage/blockstates/light_gray_grid.json 291eca6f29ecb96d444d2239296681f06863abc2 assets/refinedstorage/blockstates/light_gray_network_receiver.json 7e9130f18c7c65a21040770b227062514cb64fe1 assets/refinedstorage/blockstates/light_gray_network_transmitter.json 2f51485ac6f31c6fc7f2c4b40dd6512ed191f441 assets/refinedstorage/blockstates/light_gray_pattern_grid.json 8d872d41d7c5d7938323ed7f1c0dfeb052e475d1 assets/refinedstorage/blockstates/light_gray_relay.json 568c5af660f6e73cbed6a0d71c1e7cd104789f38 assets/refinedstorage/blockstates/light_gray_security_manager.json e04c8bfa9649765ff0faa30e8399786d56082006 assets/refinedstorage/blockstates/light_gray_wireless_transmitter.json 9664192d13467956a09e888ca2842539beb097dd assets/refinedstorage/blockstates/lime_controller.json 569b62896e4ae49fd7979d028950a7c908eade31 assets/refinedstorage/blockstates/lime_crafter.json f05e8def107036b057cfadd75cfc52f08da5978b assets/refinedstorage/blockstates/lime_crafter_manager.json b01d62bbba055517755be182585aec9972775111 assets/refinedstorage/blockstates/lime_crafting_grid.json 1d5b0778259ae1c2f1ca523f8f1b6e6353935d51 assets/refinedstorage/blockstates/lime_crafting_monitor.json 9664192d13467956a09e888ca2842539beb097dd assets/refinedstorage/blockstates/lime_creative_controller.json ad9f60051001a52e0b10b12e37f6210b05e2cc8d assets/refinedstorage/blockstates/lime_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/lime_disk_manipulator.json 4521dfe3f69c6168e1d72fff247ee3a3d361ff0d assets/refinedstorage/blockstates/lime_fluid_grid.json 6b5b6be70adbbc6eea356f00d7395dd2d181359c assets/refinedstorage/blockstates/lime_grid.json f1af8de9b654aac6c1e67ad5e6cd03ab7ad36b2d assets/refinedstorage/blockstates/lime_network_receiver.json ecd69149921b551c1dc18f6df43d703e83a68109 assets/refinedstorage/blockstates/lime_network_transmitter.json f0bbcee38acf700e7598ec2256dec30359f6dade assets/refinedstorage/blockstates/lime_pattern_grid.json 50bcc8668c59ea7cc18307dc9a66710bb64a01a8 assets/refinedstorage/blockstates/lime_relay.json 186f9f08d55c7eed41bdf20224a29c1da86116b1 assets/refinedstorage/blockstates/lime_security_manager.json 31f6b78d9517e14f2eaee154b2bd016b8d122e99 assets/refinedstorage/blockstates/lime_wireless_transmitter.json 260ee50fd5b48a884478722a48d1a30718011b71 assets/refinedstorage/blockstates/magenta_controller.json a4fd0d98391e23b4fb5eeb263aa4b3a4a0e8463c assets/refinedstorage/blockstates/magenta_crafter.json 334f9cd98067974c61d760b955499868cade5541 assets/refinedstorage/blockstates/magenta_crafter_manager.json 6120e96957450ae3ddae9f45159144d6bd5eba88 assets/refinedstorage/blockstates/magenta_crafting_grid.json f37fd6d2cf884ea50df0e3498d4a1c79ab119643 assets/refinedstorage/blockstates/magenta_crafting_monitor.json 260ee50fd5b48a884478722a48d1a30718011b71 assets/refinedstorage/blockstates/magenta_creative_controller.json be4821c7ef7e2e092182daeae240ca64ac64109c assets/refinedstorage/blockstates/magenta_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/magenta_disk_manipulator.json 015ec2f4a5391216b726c6f3a04e207aef8eb73f assets/refinedstorage/blockstates/magenta_fluid_grid.json 4df8d4e340437e044e274b93cbd3f530481b9a9c assets/refinedstorage/blockstates/magenta_grid.json 52ba7a0be6c7745dcf6c8dce2ee714c3e435a6be assets/refinedstorage/blockstates/magenta_network_receiver.json 10dd4186b77550077274cf71093f9ed5e669f6f7 assets/refinedstorage/blockstates/magenta_network_transmitter.json 0cd180c166969d567fd19b20335b3a79c58a5b5a assets/refinedstorage/blockstates/magenta_pattern_grid.json cd0a58993fd70d4f45125bba65df310cf636e8b6 assets/refinedstorage/blockstates/magenta_relay.json 97be2ff3849c198bb435104273d6242b2394ed26 assets/refinedstorage/blockstates/magenta_security_manager.json 448d11572eb6e83a9c83bdc59a5db04b0bdf4055 assets/refinedstorage/blockstates/magenta_wireless_transmitter.json c02181173dfdc836b36270f2d53047e768bd4d65 assets/refinedstorage/blockstates/network_receiver.json d7ceb07865dd4532faa78a2292e35c6b47d5b5af assets/refinedstorage/blockstates/network_transmitter.json 59cbfcaabd03f853aca3f60329a7c95cb787c8e6 assets/refinedstorage/blockstates/orange_controller.json c2e934d8f8332b9ef9f4860e0c5f5fc3e437fa9c assets/refinedstorage/blockstates/orange_crafter.json 827f42cfab50b0dd2ed5b5d9f76094028c9be5b3 assets/refinedstorage/blockstates/orange_crafter_manager.json c770a2427a6474bdd86d98494c8685fca33ee741 assets/refinedstorage/blockstates/orange_crafting_grid.json c979c60e1dfc954dd55ec707707f0ff6e892c4de assets/refinedstorage/blockstates/orange_crafting_monitor.json 59cbfcaabd03f853aca3f60329a7c95cb787c8e6 assets/refinedstorage/blockstates/orange_creative_controller.json c33a89682e5a55748c59b150cada12a9d1b9c55d assets/refinedstorage/blockstates/orange_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/orange_disk_manipulator.json c32fe65c75f75ef6d2b2f6b88022d950403f4a69 assets/refinedstorage/blockstates/orange_fluid_grid.json 2df3a077ef494d1296f566de4023d26569b31eee assets/refinedstorage/blockstates/orange_grid.json 46f988c8980d2ef48ae7abd74c79dd5e7e017f8d assets/refinedstorage/blockstates/orange_network_receiver.json 62ccc839c105f9668dc3c12f6ea696006fd2362d assets/refinedstorage/blockstates/orange_network_transmitter.json 0433e6562309eb58a721431184c99a52842a5386 assets/refinedstorage/blockstates/orange_pattern_grid.json 94b7f4ea5bfec14b016f8994659f37cc725f1481 assets/refinedstorage/blockstates/orange_relay.json 52977b1a88ecd1065a83ada462b5a8a550abd549 assets/refinedstorage/blockstates/orange_security_manager.json 93ad3d01bc10971f9e4f5c2d83f267fd458fb4b0 assets/refinedstorage/blockstates/orange_wireless_transmitter.json 853d43993b0ff5412f8664107e4602f7c9108670 assets/refinedstorage/blockstates/pattern_grid.json e124d2cc9470854729e26e8bc95e82c8d12d66b3 assets/refinedstorage/blockstates/pink_controller.json 72d722e540d986a161de430d090812cbb6bec108 assets/refinedstorage/blockstates/pink_crafter.json ba83f5db4d49f98108667801a53b8dffd59bd984 assets/refinedstorage/blockstates/pink_crafter_manager.json 8648689ae33328eaefbfcf5bd4c52b61afb38138 assets/refinedstorage/blockstates/pink_crafting_grid.json 66584320c7486816c3fcf9b28ed7af70a146a235 assets/refinedstorage/blockstates/pink_crafting_monitor.json e124d2cc9470854729e26e8bc95e82c8d12d66b3 assets/refinedstorage/blockstates/pink_creative_controller.json 69fd216404681bf23ad1c7c117e4f7976a355ad8 assets/refinedstorage/blockstates/pink_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/pink_disk_manipulator.json b67fc2fcdb0a21fd36d258e53516cd9f876d4dfb assets/refinedstorage/blockstates/pink_fluid_grid.json 73dbf1f3d783ebe6e191b4646b56cdab6b3f6e2e assets/refinedstorage/blockstates/pink_grid.json 10e8d8a00049240ae65eeae04c95701f632245fc assets/refinedstorage/blockstates/pink_network_receiver.json 3e808dbbcb61a670355520bed140d12952b74915 assets/refinedstorage/blockstates/pink_network_transmitter.json 0bf4783a34fc70b08f825fc1884afeafaec1c2eb assets/refinedstorage/blockstates/pink_pattern_grid.json b408e8eb93f9bb1c384ab447af269e1d6291f359 assets/refinedstorage/blockstates/pink_relay.json 3c5ce44160aa8718c9c703ee9088949b8c0592f0 assets/refinedstorage/blockstates/pink_security_manager.json c005a1b1d19d4d8a0bd5554ea0bdfc0215dcf22f assets/refinedstorage/blockstates/pink_wireless_transmitter.json 49b1d9978995934a26559798c700dcc6f62f07ce assets/refinedstorage/blockstates/purple_controller.json 17cf9e787325d128382838783327f03664c81700 assets/refinedstorage/blockstates/purple_crafter.json 975ad7db8e483731a66f57cfb06f579fff2d2611 assets/refinedstorage/blockstates/purple_crafter_manager.json 926110729d03c21d259ef4f44d43dc17e6e5c828 assets/refinedstorage/blockstates/purple_crafting_grid.json 34180be7994fcb0700b90090cb2a73f18506e28c assets/refinedstorage/blockstates/purple_crafting_monitor.json 49b1d9978995934a26559798c700dcc6f62f07ce assets/refinedstorage/blockstates/purple_creative_controller.json 47fe9b00de7749597a2846508c2dc423ca53c943 assets/refinedstorage/blockstates/purple_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/purple_disk_manipulator.json f7bad620df59f5fdc15bd7648e29ff56c58fdcb2 assets/refinedstorage/blockstates/purple_fluid_grid.json 8dbb3d3793866969367ceb33c5d0fa2a57114f89 assets/refinedstorage/blockstates/purple_grid.json b5b0f4e65c5729b3d291b2a180eef162d6065368 assets/refinedstorage/blockstates/purple_network_receiver.json bc53f00fe156eb3e7fda7cc515c32c5e325a8574 assets/refinedstorage/blockstates/purple_network_transmitter.json fafd9a507ac856250fe79ebf77591aa48978517d assets/refinedstorage/blockstates/purple_pattern_grid.json 42e4fdd1f5c123b3857c94cd27a376998f5f4c99 assets/refinedstorage/blockstates/purple_relay.json c70b3c0c23bd2f910a185d8c1704b10e4d7e7f55 assets/refinedstorage/blockstates/purple_security_manager.json 6191786c1b4688b83ce872b46998e2769fe315a9 assets/refinedstorage/blockstates/purple_wireless_transmitter.json 0af344822971927dbabc9a3248c4b065f57380da assets/refinedstorage/blockstates/red_controller.json d15483f33e14d52b696c148fc35074555ac34dc2 assets/refinedstorage/blockstates/red_crafter.json 01bbcbd3539bae6de40adb47e0f718c77d12fe0e assets/refinedstorage/blockstates/red_crafter_manager.json 9587b8ed2ad59cc4701de701117dae551bfa9f28 assets/refinedstorage/blockstates/red_crafting_grid.json ccb731fe0e6f98f5ba987f1f628c0c643b43d2bc assets/refinedstorage/blockstates/red_crafting_monitor.json 0af344822971927dbabc9a3248c4b065f57380da assets/refinedstorage/blockstates/red_creative_controller.json 3535214510b28671e75e83091ed892a2ace93fe2 assets/refinedstorage/blockstates/red_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/red_disk_manipulator.json 2b0831c043a5db5801a83056db001bc9bea3e10d assets/refinedstorage/blockstates/red_fluid_grid.json 08ea6c75ab709d59b644a9b6f851b30297709c37 assets/refinedstorage/blockstates/red_grid.json 54c11f3818805a1f8c642fe9b39f8172cd0dbe9d assets/refinedstorage/blockstates/red_network_receiver.json 306ea9c1b5e720034d4a64216a246f66ff378374 assets/refinedstorage/blockstates/red_network_transmitter.json 0c146705612be3767b5580be6bdd2191da080f6d assets/refinedstorage/blockstates/red_pattern_grid.json 7824d4a6b0a909bd130b3c9b03499d5303c00d48 assets/refinedstorage/blockstates/red_relay.json 11a0de95d22a08e07cb7bccb5ee11b6998910aa8 assets/refinedstorage/blockstates/red_security_manager.json 568aa0fb5ede635323c6fccdc4f07f4242a02eab assets/refinedstorage/blockstates/red_wireless_transmitter.json be302ad36912be59948baac2e7ec7d458f7ba790 assets/refinedstorage/blockstates/relay.json eca4522120aade2750f46407dd0c4f3a622481f9 assets/refinedstorage/blockstates/security_manager.json 91dc10e68eccb57db9c8ba9c8740a586858d6b1d assets/refinedstorage/blockstates/white_controller.json 5af23026e097081db875ac14160d957c84ffb683 assets/refinedstorage/blockstates/white_crafter.json c8db46d5b6688983ca6713252b618c8b854f6c48 assets/refinedstorage/blockstates/white_crafter_manager.json 65d789e8e0c1b327477301f435bfd4f02e987379 assets/refinedstorage/blockstates/white_crafting_grid.json 5e9fb377bcb1d89b7911e730121c575d42aee270 assets/refinedstorage/blockstates/white_crafting_monitor.json 91dc10e68eccb57db9c8ba9c8740a586858d6b1d assets/refinedstorage/blockstates/white_creative_controller.json 0841cf91a7f73f743fe3163044a10200cf1e1d2c assets/refinedstorage/blockstates/white_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/white_disk_manipulator.json 790778184e42c85287c157671786d4bddbb46859 assets/refinedstorage/blockstates/white_fluid_grid.json c1cc1d5d09eaa77e3e2063f5fc67c938ae73bc1e assets/refinedstorage/blockstates/white_grid.json 6c0bd32d1ef222adf37252e798941269db9561d0 assets/refinedstorage/blockstates/white_network_receiver.json ef79c48970c517a4466bca9c79a3f72ee94b2739 assets/refinedstorage/blockstates/white_network_transmitter.json 9582df2542be982efafea176a8a95f8f4ee33ae7 assets/refinedstorage/blockstates/white_pattern_grid.json 452c484028c224bbed3d37e630f87d9c47025557 assets/refinedstorage/blockstates/white_relay.json 3959a8de59e67d553d87f85b02563d49fd7024ae assets/refinedstorage/blockstates/white_security_manager.json fdd7b224242f0c9d725fe4fe856359a19cde73e8 assets/refinedstorage/blockstates/white_wireless_transmitter.json 1bb50b333ed68b51fb4068ad1a294a1721afe6fb assets/refinedstorage/blockstates/wireless_transmitter.json 354e5098e85da4653b9f75a96f3bbae3b39cd4dc assets/refinedstorage/blockstates/yellow_controller.json 7f5ef4baae9693d421b3b4eef67cfbb6fcb86efd assets/refinedstorage/blockstates/yellow_crafter.json 1cb9354c8fc7094f9329fd21d0d6d8de6ebe70c2 assets/refinedstorage/blockstates/yellow_crafter_manager.json 698d185106d288e3e7b5162298d1cdb2719ebad1 assets/refinedstorage/blockstates/yellow_crafting_grid.json 893f864c644153a9883f6bedff779622057afd8d assets/refinedstorage/blockstates/yellow_crafting_monitor.json 354e5098e85da4653b9f75a96f3bbae3b39cd4dc assets/refinedstorage/blockstates/yellow_creative_controller.json 2ab0f370e0f93617df8f9244bd147d2ca03cb418 assets/refinedstorage/blockstates/yellow_detector.json 6714b970975b3b5d82f167505f497b00e5e7cf3d assets/refinedstorage/blockstates/yellow_disk_manipulator.json a53c34950d398e238e5e00f846ab7b9f5613b137 assets/refinedstorage/blockstates/yellow_fluid_grid.json f1a1ea426ae7caf8668631858f2943cdeba922c1 assets/refinedstorage/blockstates/yellow_grid.json 3df04e5fd0be4f4bc3f590aa7b18cfc2e62a6970 assets/refinedstorage/blockstates/yellow_network_receiver.json 9b04ef1034b8f0f53a331fca4a7a7f853b219f53 assets/refinedstorage/blockstates/yellow_network_transmitter.json cb0c6edbce8a2ce0255c8b3a3a9cd1cc8741a71a assets/refinedstorage/blockstates/yellow_pattern_grid.json fe89e69e7c6bf1e1863f8e9ee2fe3cacf27c3bf4 assets/refinedstorage/blockstates/yellow_relay.json 3cce759ae50cb0c471c9e0173dc3d8beb18e7c5b assets/refinedstorage/blockstates/yellow_security_manager.json 37ef58994e615ff1285ef554521dc1c5dc7f68aa assets/refinedstorage/blockstates/yellow_wireless_transmitter.json 7dd4d790b7ab67ac05a5465e93a5df75f0a19a7f assets/refinedstorage/models/block/controller/black.json 7ce5a4227982e3dbed579e8c9efe192ec3a46814 assets/refinedstorage/models/block/controller/blue.json 35aa8942bfca9ebb5593b06192b1337298a91566 assets/refinedstorage/models/block/controller/brown.json 4a7bc6807440bdacaf4a388001fff0af2178055d assets/refinedstorage/models/block/controller/cyan.json 59f918515830678508a58682d629ade5c7f127a6 assets/refinedstorage/models/block/controller/gray.json 533baa9de3602004178156576cc1c50b82970253 assets/refinedstorage/models/block/controller/green.json 55ffca09db55f6ff3651df021853cb4c67971d4c assets/refinedstorage/models/block/controller/light_blue.json 48afa16ef64605e47f8ef0718a04fe0ea4497be8 assets/refinedstorage/models/block/controller/light_gray.json e25236415255c8e84e8425cd5ef5068af2e90bf5 assets/refinedstorage/models/block/controller/lime.json 719f9943433757fe6d544facfad02cf5c863b128 assets/refinedstorage/models/block/controller/magenta.json ac1cb6e399a675e681a5c32be92cf2bbbabb845e assets/refinedstorage/models/block/controller/nearly_off.json df5ef8ae2db4d693376007210753f08e8ed9aa1f assets/refinedstorage/models/block/controller/nearly_on.json 649b3ac449fa858abcf8771bc91fe9ce04949989 assets/refinedstorage/models/block/controller/off.json 197c8d6037075f2a32aa361a573a86a93b71d178 assets/refinedstorage/models/block/controller/orange.json b5d54a0751d165ea36f32a545cd0d74cfec96138 assets/refinedstorage/models/block/controller/pink.json f6f6681357c6759a6de3baac9116c45f4027ed0b assets/refinedstorage/models/block/controller/purple.json d940dae104b67d6bb4eaadfa5c196d174cea0dd9 assets/refinedstorage/models/block/controller/red.json c5377c73ba6e75dcfd191f1c28769bc380aa4447 assets/refinedstorage/models/block/controller/white.json d5b65da238fd3119c615a589bcab6c32b93a2838 assets/refinedstorage/models/block/controller/yellow.json a3fc2ae7524e81e7ac41d116f23dfcfe58fcca9a assets/refinedstorage/models/block/crafter/black.json ca9f47ac28aa1e6779613d426b837526b50ae0e2 assets/refinedstorage/models/block/crafter/blue.json 58a500649c2d2a496f7228b9fa537802baf15a20 assets/refinedstorage/models/block/crafter/brown.json cce737a93507d1eb58d51d2ddac6428c695c6b23 assets/refinedstorage/models/block/crafter/cyan.json 9a012e8377cf60c903a5d42918f3b2bde17539d2 assets/refinedstorage/models/block/crafter/disconnected.json 7c6c30838702c3e43f7c9e62319d2cd486d1498a assets/refinedstorage/models/block/crafter/gray.json c495e9d2fc43e5e6094b4799609961445d391927 assets/refinedstorage/models/block/crafter/green.json 8c493f345d1a6af778087a49cf36588954bb84fe assets/refinedstorage/models/block/crafter/light_blue.json ce28ae9ae0553978724a134087ec1e836d1d7b84 assets/refinedstorage/models/block/crafter/light_gray.json 6d79cebd8c01ae4fd0f13914a9a0f15ed91fd8f0 assets/refinedstorage/models/block/crafter/lime.json 08d8c9040d77c717581b2ae3d485e0ffc5dd0d83 assets/refinedstorage/models/block/crafter/magenta.json 6952bdf6763143f35b9d80a42e3cc354cc4da15d assets/refinedstorage/models/block/crafter/orange.json dd40faae420cdb526883f24a052992bf9b5c17a5 assets/refinedstorage/models/block/crafter/pink.json 3bcb7dcb9b8a6c8d6425d788e794ce84a62a1f91 assets/refinedstorage/models/block/crafter/purple.json da30ebf53613bc7a7add1af2fd149f3497ad394a assets/refinedstorage/models/block/crafter/red.json 6c4add52ccbfc051ed8deda52c3664c35a96cc36 assets/refinedstorage/models/block/crafter/white.json ead08d7a0ba6b368d8c9afb2907f3495ebc0238f assets/refinedstorage/models/block/crafter/yellow.json c1ab462d97a36b71baa6d03b0aefab777377aa80 assets/refinedstorage/models/block/crafter_manager/black.json 947d1cacb3f457c5f9985961bf9a2cb64392f9c6 assets/refinedstorage/models/block/crafter_manager/blue.json bdf1b91bb479fdc377250a925dd569c222b8b983 assets/refinedstorage/models/block/crafter_manager/brown.json 41746225550b6f965c0bcb2168aef5afa6ac5780 assets/refinedstorage/models/block/crafter_manager/cyan.json 006345975c1de5fb804ad47027d66730f13676d9 assets/refinedstorage/models/block/crafter_manager/disconnected.json 7470d98e9ed8ab00a4cac8b651d095dbc33a787a assets/refinedstorage/models/block/crafter_manager/gray.json a6b801087e0e0311fa660ae060879aede938bfa0 assets/refinedstorage/models/block/crafter_manager/green.json e6d7a1289f13a29a429db62287ac6c3143a9565a assets/refinedstorage/models/block/crafter_manager/light_blue.json 77c0967108d7a410b69ebdc3d2b5606b653aca4f assets/refinedstorage/models/block/crafter_manager/light_gray.json 341e45f850f25ba40d3af0ae3b269782c345db7e assets/refinedstorage/models/block/crafter_manager/lime.json ec810637edf5e6cd5a52c21d7d01d76c0e12a5d0 assets/refinedstorage/models/block/crafter_manager/magenta.json e20e3f306648768835867ba976b0ba1f6ab7d48e assets/refinedstorage/models/block/crafter_manager/orange.json a67381c44b22482008ab6f9b7474987764b838ea assets/refinedstorage/models/block/crafter_manager/pink.json c5b8ef34fd2b4c39efe5dfe3eff38f2631be9233 assets/refinedstorage/models/block/crafter_manager/purple.json cc006d4e8b49165ab3d3dc584f7e68415dffb36c assets/refinedstorage/models/block/crafter_manager/red.json 6dbf08216a746ed970af93d43870cf9aff8e9398 assets/refinedstorage/models/block/crafter_manager/white.json a65b6a6e90137b5b6d061637daca39cf0230a756 assets/refinedstorage/models/block/crafter_manager/yellow.json 4f4c3f024920850c65a87faeac77dd3659915287 assets/refinedstorage/models/block/crafting_grid/black.json f1beacefdaf9aae0aaafc5a3c5e865e84173c2d4 assets/refinedstorage/models/block/crafting_grid/blue.json 3f85170b187def3b075ec11982f91775c72ea2bb assets/refinedstorage/models/block/crafting_grid/brown.json e3a6ddbf8c7348f8f0678b7b88d7309c1c2048fb assets/refinedstorage/models/block/crafting_grid/cyan.json 6cc5581bebc7eaa3b6ab156aec032534afa56b89 assets/refinedstorage/models/block/crafting_grid/disconnected.json c483c28bc8d003c214cd9d2c7de40500d9a14a5e assets/refinedstorage/models/block/crafting_grid/gray.json 53c5036ea2fd4bc481bccdcd3f37f4b4a3c0e25f assets/refinedstorage/models/block/crafting_grid/green.json 034ce68bb933818291cc7b28b6c5da5471c16f01 assets/refinedstorage/models/block/crafting_grid/light_blue.json 40ff2912140c39bd37734b18941d595d6308aac8 assets/refinedstorage/models/block/crafting_grid/light_gray.json de80e07454eb9b8ad33af7a722d0fb0edc39ff56 assets/refinedstorage/models/block/crafting_grid/lime.json 1e02f68733741502624b4726ed521063efa3373b assets/refinedstorage/models/block/crafting_grid/magenta.json 60030a6c0d21492b10b027495cdec7d551592778 assets/refinedstorage/models/block/crafting_grid/orange.json 35609d8acbf324629aa92ac49ae0f64f9126989b assets/refinedstorage/models/block/crafting_grid/pink.json a43ebf377c637ae6a90699ef5895241645d75020 assets/refinedstorage/models/block/crafting_grid/purple.json 8e685875e33fa52f88ddef1de0c370bbc1fc0717 assets/refinedstorage/models/block/crafting_grid/red.json bfb178e21d7b46750737a1451ea29d57456d1763 assets/refinedstorage/models/block/crafting_grid/white.json a69aa2d1c9aa0c0670d60c0f88cfa07ebe8d258c assets/refinedstorage/models/block/crafting_grid/yellow.json e40a7af2d99a7ff0847a13865339fa00a3ebc439 assets/refinedstorage/models/block/crafting_monitor/black.json 52a2c625eb84f7586bdb98d8f709ffb3c17e4ee9 assets/refinedstorage/models/block/crafting_monitor/blue.json 9c8ceeee7c2dc1512e23d3798c51fa75387d411c assets/refinedstorage/models/block/crafting_monitor/brown.json 1d071a43fa223ffd8261704132df37b8ee916a1d assets/refinedstorage/models/block/crafting_monitor/cyan.json 8cc27a1d4bf9f12010581454f1d78aa1d982b3ac assets/refinedstorage/models/block/crafting_monitor/disconnected.json 1e2f04d1521c27e31f06940684c1ca7306fa3524 assets/refinedstorage/models/block/crafting_monitor/gray.json ddf85353932580ced34a09ce5cd5fc121828e90d assets/refinedstorage/models/block/crafting_monitor/green.json a161a5fa71b287a0eb7ff801458ad5c76a55a7c5 assets/refinedstorage/models/block/crafting_monitor/light_blue.json 8066136befa4b7e2d5cefdf9350f64b995051226 assets/refinedstorage/models/block/crafting_monitor/light_gray.json 3671b90902d442e18c4fb13d3e50756d7532be8e assets/refinedstorage/models/block/crafting_monitor/lime.json d94ce990ec267a992686830fbcf10a43c23196cc assets/refinedstorage/models/block/crafting_monitor/magenta.json cf4753ad43dbf73db3696dd4c19849e6a2b9a33c assets/refinedstorage/models/block/crafting_monitor/orange.json cc142ac9d63ebe6bc9a8f94a39ac89d71565d569 assets/refinedstorage/models/block/crafting_monitor/pink.json 5c0ff643784ef39a297f050e4bdff46ca2b1cce5 assets/refinedstorage/models/block/crafting_monitor/purple.json f1e3b6c58f99ac64ab48d2c735b8d675f9c74a0e assets/refinedstorage/models/block/crafting_monitor/red.json 08fe3f165275166eee5557a0c6edfbd4035eae8b assets/refinedstorage/models/block/crafting_monitor/white.json b99b33fed141c1c979c4f68ac0e656ddacb7b041 assets/refinedstorage/models/block/crafting_monitor/yellow.json 2b8f350a8b1fb249e9b835aab5969f4bd76a6ea7 assets/refinedstorage/models/block/detector/black.json c7298157a39315ff38d1310b4ebe77c708cf8a82 assets/refinedstorage/models/block/detector/blue.json 298af9d65b3e2334de2519ef7e19c78756c1ab99 assets/refinedstorage/models/block/detector/brown.json d764ac8e477068bbb296c3854ad76a7b80d1d44a assets/refinedstorage/models/block/detector/cyan.json 50d618e3cb55a96d67dcc9a6b42bd17c58e1870c assets/refinedstorage/models/block/detector/gray.json 7845acde95c218ca098ec30a2e568b3334f09944 assets/refinedstorage/models/block/detector/green.json c735ce9091c7a5ab2eb0c7b162af77c2ffac2ad8 assets/refinedstorage/models/block/detector/light_blue.json b462ca74227c62a9e8567ab7461f45e5e95425d8 assets/refinedstorage/models/block/detector/light_gray.json 4f52368581621adf1d799660c42f108207217575 assets/refinedstorage/models/block/detector/lime.json 170d5328b3f1d9c05c2f6af3191a42d734e89e2b assets/refinedstorage/models/block/detector/magenta.json f50f9956dc7bdd3cac13a6473a45906050667a78 assets/refinedstorage/models/block/detector/off.json 2c735eca8fcf7770558758a49f7f8ea469225897 assets/refinedstorage/models/block/detector/orange.json d795e18038baa420972781d7206c1809c7297ae8 assets/refinedstorage/models/block/detector/pink.json 0fe0d9e192b473fdb4cc8a5844ca44de22364e43 assets/refinedstorage/models/block/detector/purple.json d07f6cedd294574ead99b3b024206c0126b26896 assets/refinedstorage/models/block/detector/red.json a792d3daf2709048bf14ee378c7362b05c938bff assets/refinedstorage/models/block/detector/white.json bb3725144c25a75f4e0e0a47e7efd174b7211261 assets/refinedstorage/models/block/detector/yellow.json 1785659b9e89cb0d4f027bc97e3a5812c8b1ccdb assets/refinedstorage/models/block/disk_manipulator/black.json 08feb52f08c96567bbdc6cd0ab9f289748c3bd1c assets/refinedstorage/models/block/disk_manipulator/blue.json 5050a32ef1afdb15f31f169d257596a29cf0e46d assets/refinedstorage/models/block/disk_manipulator/brown.json 9900ae5b9004204fea75cad20e4b18a6d8d3ec37 assets/refinedstorage/models/block/disk_manipulator/cyan.json 46b21908098b41f5a6a4229d941dd4732ef1dd76 assets/refinedstorage/models/block/disk_manipulator/disconnected.json 8f78635bbb9015e9b3c710418adec9b96570b133 assets/refinedstorage/models/block/disk_manipulator/gray.json 588bb56e49677311063aa0eee9ebbb864e528fc0 assets/refinedstorage/models/block/disk_manipulator/green.json 46677b54fec1f540a8d63e8037bbf164f755b995 assets/refinedstorage/models/block/disk_manipulator/light_blue.json 2dc951c9ebb27963eab8bd4e311da3e3f6ad99e9 assets/refinedstorage/models/block/disk_manipulator/light_gray.json 08cf44fa79c6e90f420e3eeb2e02c52f875c06ff assets/refinedstorage/models/block/disk_manipulator/lime.json 72d202c30b016055cecc9084d61e5bbadfa0a761 assets/refinedstorage/models/block/disk_manipulator/loader.json b4355a9e686dece664cd7a2129724823e0315abc assets/refinedstorage/models/block/disk_manipulator/magenta.json 577215970d538ba411e951ee561c71edf4719876 assets/refinedstorage/models/block/disk_manipulator/orange.json b6a061ad8d84445979b2eddda4851ea7fe4557f2 assets/refinedstorage/models/block/disk_manipulator/pink.json 4296e50c7de8c775143eb16d5e75c3804b0ee19c assets/refinedstorage/models/block/disk_manipulator/purple.json 28244ffee47ac3ef6ccbd3228d7db8ffe8f8f00f assets/refinedstorage/models/block/disk_manipulator/red.json d7c7712fe9dc02e0bde2ed57f5e886698b5d1d65 assets/refinedstorage/models/block/disk_manipulator/white.json 15c40e7373bff9f0a9e254aaf6d4aa9e3d2a1d53 assets/refinedstorage/models/block/disk_manipulator/yellow.json 7af6b31d785047fff3d4716c81fbf550a38f292b assets/refinedstorage/models/block/fluid_grid/black.json 2cc6db45ec512f617d3dfc74e56c812700e8c9be assets/refinedstorage/models/block/fluid_grid/blue.json 043ee02c82d506d6f5024246fafdf467bcba50f4 assets/refinedstorage/models/block/fluid_grid/brown.json 92c6f3c28c41f179c507434f9e13c41fb6713942 assets/refinedstorage/models/block/fluid_grid/cyan.json 8715a94eb3b672cf941e471c5883cc9ddebff362 assets/refinedstorage/models/block/fluid_grid/disconnected.json 328db8a51dac5c943b005dd8178f70de0e69b03d assets/refinedstorage/models/block/fluid_grid/gray.json 3a012b462e69bdca95c5bb3e030d8dea2d438539 assets/refinedstorage/models/block/fluid_grid/green.json 7f05d7725b608fdb70ba2ae4c6ade712912b5d30 assets/refinedstorage/models/block/fluid_grid/light_blue.json 95d50b03de3385f617aa2d9641af547fbed68ae3 assets/refinedstorage/models/block/fluid_grid/light_gray.json 536cd514850a06a78582bc93f44fb1fe81460ccc assets/refinedstorage/models/block/fluid_grid/lime.json 511ea39721de8eaf9de4962eb0a953f460445c98 assets/refinedstorage/models/block/fluid_grid/magenta.json 93073d28da8386afb465c093c7c9a805faa5e843 assets/refinedstorage/models/block/fluid_grid/orange.json 34070d257c6e5fa057a914ace02db59fc4317c15 assets/refinedstorage/models/block/fluid_grid/pink.json 2d400582419ad444bf5950deac5da692cb1ad9ae assets/refinedstorage/models/block/fluid_grid/purple.json 6361903f6b6ff8f817e4511601b47990599f1edc assets/refinedstorage/models/block/fluid_grid/red.json 6886951919ccfce485e851045fa23ff7deddf9be assets/refinedstorage/models/block/fluid_grid/white.json 37e31039cba0204a03df2fa2130dc2383d303d29 assets/refinedstorage/models/block/fluid_grid/yellow.json e845c4a37c72d5ad426fac7203353a9665648a46 assets/refinedstorage/models/block/grid/black.json 589f51309dbecb1964c070a70496b79ae1c4ebcb assets/refinedstorage/models/block/grid/blue.json 437076a560cbafb39c685b88e6fd2073c7c158d0 assets/refinedstorage/models/block/grid/brown.json 49f3eb8374ee309b81f9242bd048f66421eaa75e assets/refinedstorage/models/block/grid/cyan.json 97d78c65ba856ead9ff344625e37ed4f6f880516 assets/refinedstorage/models/block/grid/disconnected.json 3ad1130e18a706495810f1cc32e2658b4910607a assets/refinedstorage/models/block/grid/gray.json 83b393342de4c5aee81c50715479ec78efb21667 assets/refinedstorage/models/block/grid/green.json 3fb70b9aba3dbe38bc0279f1b2789695f8e0a784 assets/refinedstorage/models/block/grid/light_blue.json 0ea1bb0f7196763e843c2bfe7b6a24356af72768 assets/refinedstorage/models/block/grid/light_gray.json 0aa895ec1c87aa4d982f8ff244d7a9efa541183e assets/refinedstorage/models/block/grid/lime.json 3fdd4ff86575596e397c27025b12b78475c6a0af assets/refinedstorage/models/block/grid/magenta.json 700fdb55791027e838a317d60296ba99dcece579 assets/refinedstorage/models/block/grid/orange.json 63797a1d7f8c29bf803200cd6e20565e4fe6e56e assets/refinedstorage/models/block/grid/pink.json 1dab675f1583f789f2677c597bfd42cd1d310be1 assets/refinedstorage/models/block/grid/purple.json 06a1e40dd45c7650699eead04d99397f745cd39b assets/refinedstorage/models/block/grid/red.json 329229e786e1a6e0f36c547bd8f7e8e3adcd5f08 assets/refinedstorage/models/block/grid/white.json b6ad5c9d362ca9c4cbb5727be2a3ea38f03e0a64 assets/refinedstorage/models/block/grid/yellow.json 79526257476cca709b95852c87d9e193ae645074 assets/refinedstorage/models/block/network_receiver/black.json 521b606adc714ae111325cfb4b86c2f00fc49838 assets/refinedstorage/models/block/network_receiver/blue.json e988e5bf8a325e3ed5e80e5615e8d5b337e92892 assets/refinedstorage/models/block/network_receiver/brown.json 9feb023af7e1f64c0586fcaa67059743deb3da04 assets/refinedstorage/models/block/network_receiver/cyan.json 978191a2fcbf46cfd70fe9e4bfa564a3b1b89336 assets/refinedstorage/models/block/network_receiver/disconnected.json 44587865547f9c2e58421ea0a880ff51cf8b8fbf assets/refinedstorage/models/block/network_receiver/gray.json 180555a0b56ddbe2def2b86d44ad8d8747bffbea assets/refinedstorage/models/block/network_receiver/green.json cd3a8952d2246b8ae436f6b6b66ee7f7f3f51fa7 assets/refinedstorage/models/block/network_receiver/light_blue.json 46a376a32289cef91d22fddc292ebff32ca4d2cb assets/refinedstorage/models/block/network_receiver/light_gray.json 09a5924b295c3b1a3668cd9523c2bb9f46a320bc assets/refinedstorage/models/block/network_receiver/lime.json 9233ffacf2b28e6feaa1b119996d4eb2cdfa1363 assets/refinedstorage/models/block/network_receiver/magenta.json 16e69b8fee05153dc0664b24b88cf954c6b20fb6 assets/refinedstorage/models/block/network_receiver/orange.json 2c0a43f2a69b4d78493d9af87b056f38b0c9b6b3 assets/refinedstorage/models/block/network_receiver/pink.json 1ada9d35a3ed9942d5e50346f21dbcafc3b9199e assets/refinedstorage/models/block/network_receiver/purple.json acc750e5d48c10a4c638f0c86d3f721c75333606 assets/refinedstorage/models/block/network_receiver/red.json 4067e93a775337668dbfb612b2d4fb411b43a6a9 assets/refinedstorage/models/block/network_receiver/white.json 6d8e8c64a39485cba7b479337426f4f7319b8d77 assets/refinedstorage/models/block/network_receiver/yellow.json c17ae790076c791a6f51b86f307c71452a47e5b9 assets/refinedstorage/models/block/network_transmitter/black.json c4e1615846d83ab4c806b6b24373be722261d1f3 assets/refinedstorage/models/block/network_transmitter/blue.json 0f59245da158e77b1cf84cfab5164eeb8814384d assets/refinedstorage/models/block/network_transmitter/brown.json d1dd664110221c97fe2d22a111800cd2b6df6982 assets/refinedstorage/models/block/network_transmitter/cyan.json 7fad44f8c99b39fa763f603e3f30fa67abebd566 assets/refinedstorage/models/block/network_transmitter/disconnected.json 8d516cc91c6e1bd3fb8e2eee31e268bf10b590df assets/refinedstorage/models/block/network_transmitter/gray.json ce9afe78c7f30a826630135797ca4c90f7cccbb8 assets/refinedstorage/models/block/network_transmitter/green.json 3a230a4a14c2151ac1de52072514b622a4fac746 assets/refinedstorage/models/block/network_transmitter/light_blue.json 754dee3959694a095c12735306116793453d34d0 assets/refinedstorage/models/block/network_transmitter/light_gray.json 363224b570a61889ec29ec9744a8d1a0d85ccb27 assets/refinedstorage/models/block/network_transmitter/lime.json fcce3c3813f180f8158038f90f20d49bee3e0f11 assets/refinedstorage/models/block/network_transmitter/magenta.json c1ece04fd664cf9748c06f945e9c20037d215346 assets/refinedstorage/models/block/network_transmitter/orange.json 260f3dc7a7da3073e7ebd39e646f484a9a78c366 assets/refinedstorage/models/block/network_transmitter/pink.json 137cb226c908a271b70748685a385b54e63d16ae assets/refinedstorage/models/block/network_transmitter/purple.json ef2ca4a218be25d42a994a308d3a684f82aeb3e8 assets/refinedstorage/models/block/network_transmitter/red.json 49ca8fa27667cfdd1d696d0deb56c376be3a8170 assets/refinedstorage/models/block/network_transmitter/white.json 594e5350dd5d3d02769a7ba72f066545ec9d3ad8 assets/refinedstorage/models/block/network_transmitter/yellow.json 92cbce2a0d88d653d3efa0ffb517b44dfe21fe33 assets/refinedstorage/models/block/pattern_grid/black.json 09d8500c01a62a454e8e1a817a82e1ad19deace2 assets/refinedstorage/models/block/pattern_grid/blue.json 50406c5a5a65c0d46e91ef389cd3fd23a2b2599b assets/refinedstorage/models/block/pattern_grid/brown.json 6ce91be1821a684898a59d3a8cfbe13ba4f6b707 assets/refinedstorage/models/block/pattern_grid/cyan.json 1dfe91631ef1f12dcecc7e0e45ec7f5e9aeb53f0 assets/refinedstorage/models/block/pattern_grid/disconnected.json 3257be294252ab0a567fc96486e30b028ba6009d assets/refinedstorage/models/block/pattern_grid/gray.json b0713d7de5cd75e371bc83e9abd33e842702f1cc assets/refinedstorage/models/block/pattern_grid/green.json 5412d15ff025c0ba4bf04e74cbecb765932cb697 assets/refinedstorage/models/block/pattern_grid/light_blue.json 3abffd3cc264e735317ecb712b1db01f1d381c91 assets/refinedstorage/models/block/pattern_grid/light_gray.json fc8cf5e162ee8f030011f5e09a3fb5373c497e08 assets/refinedstorage/models/block/pattern_grid/lime.json e32a45b233d1786edb383080382a5025c6cb502c assets/refinedstorage/models/block/pattern_grid/magenta.json 57e784c0b36a70aba86e137b541198934a3e8719 assets/refinedstorage/models/block/pattern_grid/orange.json 58bc5125052ca7ce23db697ac29acea919e33ee7 assets/refinedstorage/models/block/pattern_grid/pink.json 80126ef472a778e8aa64c20c7828aa033de4b3cf assets/refinedstorage/models/block/pattern_grid/purple.json eee9128ba674f306ff5f6795468b07a1593f6431 assets/refinedstorage/models/block/pattern_grid/red.json 0ea80f03eb7eca83ec65634635f0164bfa053524 assets/refinedstorage/models/block/pattern_grid/white.json e6b978a202ab3b7096443862fc70418fab92d528 assets/refinedstorage/models/block/pattern_grid/yellow.json 35968a567e5abe3851f3833477c6b1ee8462d423 assets/refinedstorage/models/block/relay/black.json 3918e0f6307e76c72f112b9e5a26977e4b32bb1a assets/refinedstorage/models/block/relay/blue.json 2e79077645de1d34de0d3f01102d5242a577440d assets/refinedstorage/models/block/relay/brown.json a683b28b4b41949b663208e28c393746419e5f1f assets/refinedstorage/models/block/relay/cyan.json b66ed29783c7a24a7112af3d58cfb903d14535bd assets/refinedstorage/models/block/relay/disconnected.json 9705e6e41a83a5349f74e4478284f6fe8b63a6dd assets/refinedstorage/models/block/relay/gray.json 2d21af4bfa0fade473addf82032db9e3187af096 assets/refinedstorage/models/block/relay/green.json f53061187c76cce0787d11c6b800745dfd48b36a assets/refinedstorage/models/block/relay/light_blue.json a85088b47aaef37ebd03eaec92b3818f02de8463 assets/refinedstorage/models/block/relay/light_gray.json 8502941d07ca9e6ac70c02b2e03b2a870c94e92f assets/refinedstorage/models/block/relay/lime.json 81bff5b425404e1f01f6e4e815fce9eae20299cb assets/refinedstorage/models/block/relay/magenta.json e940a4ba52e06c3033c43a29fa092506fa3dd683 assets/refinedstorage/models/block/relay/orange.json 9c48be51ec6d911626bebcdea25bbfe4171c02f1 assets/refinedstorage/models/block/relay/pink.json 28844a3913a24f63b7d202e8b55a081ed3cf9301 assets/refinedstorage/models/block/relay/purple.json c3223281fef269d54225e938165d3ef4742673a0 assets/refinedstorage/models/block/relay/red.json 9bd4c02a1e524d88b722a2b81ee49fa47beb9261 assets/refinedstorage/models/block/relay/white.json d6e52eb671800d61b5565e502f395f91c5b650a0 assets/refinedstorage/models/block/relay/yellow.json 995ac6124cb9667fa89fb87eb8cf8485e7b7e197 assets/refinedstorage/models/block/security_manager/black.json e6dcfb1bfa2cd2ce4f3d3dc2aae7da3ad344bbda assets/refinedstorage/models/block/security_manager/blue.json cacca03ecf0de2bce557ca841401033c45cf4cc1 assets/refinedstorage/models/block/security_manager/brown.json e241938c7d93a4fc12a09fa9a1ee847d129e92b9 assets/refinedstorage/models/block/security_manager/cyan.json c47c799fca836d8d3ee2022acd5347c3e84836f1 assets/refinedstorage/models/block/security_manager/disconnected.json 5fcb0264b7cc0d4132cf9f18deafa366c6066f53 assets/refinedstorage/models/block/security_manager/gray.json 871b6c7a028d339a551e10d432a936e316f7910e assets/refinedstorage/models/block/security_manager/green.json f068112ed910080dfc74f2309228f2d5c41ea1b6 assets/refinedstorage/models/block/security_manager/light_blue.json 2d7bf81078298c7cb9a9d0091fc219e7253c16d5 assets/refinedstorage/models/block/security_manager/light_gray.json 7ca8fa49596d79f4d4eb61f34462cd8baad63221 assets/refinedstorage/models/block/security_manager/lime.json 449ceab92dbc8b14edc8b0fe8fbd0648910c8a38 assets/refinedstorage/models/block/security_manager/magenta.json 5b0a97090b976df2388119ffb8a8f5a4c5eae78d assets/refinedstorage/models/block/security_manager/orange.json da7ef346c5d9f2da82bfc0f15ba7cf8594bf9c40 assets/refinedstorage/models/block/security_manager/pink.json 859171bc7c84c43ef6406b3749bf235011f4bc23 assets/refinedstorage/models/block/security_manager/purple.json 04198d42366f1a9278466585994f388fc2d01fe9 assets/refinedstorage/models/block/security_manager/red.json a865ead60de383ea8e84c5c16ffdcc2fcbd2791a assets/refinedstorage/models/block/security_manager/white.json 291f61f7abfe33116b5a0c915d84160cb0db2fbb assets/refinedstorage/models/block/security_manager/yellow.json 382ba985cb3eb98190df982cf81e85f1d00d0f98 assets/refinedstorage/models/block/wireless_transmitter/black.json f338756587a7c6bce14677030543f7399aee9259 assets/refinedstorage/models/block/wireless_transmitter/blue.json 667bad1eaa409dbd56bb9db7048a029a610dc5c0 assets/refinedstorage/models/block/wireless_transmitter/brown.json eeb75332e2a0a9a10b1f5d47b8621340c3913877 assets/refinedstorage/models/block/wireless_transmitter/cyan.json 7d8cdce240042937a7a9ad14390f02f978e3b38f assets/refinedstorage/models/block/wireless_transmitter/disconnected.json 732c1094b53f66b96e04630b2e3549f1ae3f3d3e assets/refinedstorage/models/block/wireless_transmitter/gray.json 2cb3ccf208c6144c461f8b6d05e45360f88e31f1 assets/refinedstorage/models/block/wireless_transmitter/green.json f0c6cd01aa8af1558c43033433096942fdda103e assets/refinedstorage/models/block/wireless_transmitter/light_blue.json b1e599007cf64e1a4140a4180ea642c3e208d41c assets/refinedstorage/models/block/wireless_transmitter/light_gray.json e329e6a86f119589ba724bc4036922bce1f0e716 assets/refinedstorage/models/block/wireless_transmitter/lime.json efbe23834aaae087892464faccad675b344c35af assets/refinedstorage/models/block/wireless_transmitter/magenta.json 578a2d53d7d7a800200525b04d91f356e3340014 assets/refinedstorage/models/block/wireless_transmitter/orange.json c2e51f822376d1968fc07e6987f70ff069d460d4 assets/refinedstorage/models/block/wireless_transmitter/pink.json 495be998c5278225bebc0d6340640e7904e1f4cb assets/refinedstorage/models/block/wireless_transmitter/purple.json 747ea39519e81abea94ca278f2e610e7c55d342e assets/refinedstorage/models/block/wireless_transmitter/red.json c6258775f847e0957a14fdfd24dcce3116d90acc assets/refinedstorage/models/block/wireless_transmitter/white.json 556c8e5da522c6e27f8a6ee8de69fc95fafb504e assets/refinedstorage/models/block/wireless_transmitter/yellow.json 0fb53d70880b97a55241dbb04f49b9ad39048920 assets/refinedstorage/models/item/black_controller.json 942d718968e1b8d27b203bc661801d37d154b5f2 assets/refinedstorage/models/item/black_crafter.json 75ac21fb6def11be4568d2ac5ff2651f3564f25d assets/refinedstorage/models/item/black_crafter_manager.json 28891a28805f96c47409a34943342830a15e6690 assets/refinedstorage/models/item/black_crafting_grid.json ddb0a90214bf85dc8e188068f73ae2b20f82150f assets/refinedstorage/models/item/black_crafting_monitor.json 0fb53d70880b97a55241dbb04f49b9ad39048920 assets/refinedstorage/models/item/black_creative_controller.json 241b9b206acf6f4c9ac3151c4044dac213bc0670 assets/refinedstorage/models/item/black_detector.json ac9dc77f9d6ba5ee90101187aa09e406c0d14fbd assets/refinedstorage/models/item/black_disk_manipulator.json 876fc7ec3dda3568c1fd1e8d2b6ceb200d1380ab assets/refinedstorage/models/item/black_fluid_grid.json 17c651836f3308723635b7a7a1f9e879098b33c5 assets/refinedstorage/models/item/black_grid.json fac0c63adf0b1c802ebd5cdd9fc5c9dec030b35e assets/refinedstorage/models/item/black_network_receiver.json d823ba7bc1affa7af633185834d1ff582882f2e6 assets/refinedstorage/models/item/black_network_transmitter.json 6c30fa933b83c1c01d2e069167729e91ed249ec7 assets/refinedstorage/models/item/black_pattern_grid.json 61861f588ea12538786c06129c3d0a1040394f16 assets/refinedstorage/models/item/black_relay.json c634efc545854df54c57dd2bf61d6e03448742e6 assets/refinedstorage/models/item/black_security_manager.json 6a1e27442bf1512ba949fafaf135502ae0420169 assets/refinedstorage/models/item/black_wireless_transmitter.json 1df94eb9089e76129d911d793c26402ff9313880 assets/refinedstorage/models/item/blue_controller.json 2de69e179294ad396ebe181228c3e9c1787ab550 assets/refinedstorage/models/item/blue_crafter.json cdea55152a48642717bdc630f74ee6fcf1d8f667 assets/refinedstorage/models/item/blue_crafter_manager.json c75d3ac7fb95df1b57ae997f5bf9ed7aad112eb0 assets/refinedstorage/models/item/blue_crafting_grid.json 4fba5520838ccf9f88f51853ad95b9bd6c6c9b9c assets/refinedstorage/models/item/blue_crafting_monitor.json 1df94eb9089e76129d911d793c26402ff9313880 assets/refinedstorage/models/item/blue_creative_controller.json f59b716bc576eed79556110ef355fa28cf92d10a assets/refinedstorage/models/item/blue_detector.json 5f8275097f6478a4f23e1ce55dde36a5dc2e5407 assets/refinedstorage/models/item/blue_disk_manipulator.json 675c756edd54900ab155bc45d5a7134cf6dac3a3 assets/refinedstorage/models/item/blue_fluid_grid.json 99c3ceae65e98ca0eab0ab04c7739a872102bee0 assets/refinedstorage/models/item/blue_grid.json 41c944af80509024d3de1ed1c5ab74336d3787e8 assets/refinedstorage/models/item/blue_network_receiver.json 0af6f3152bc7fcd1ca79fd0adf77d1a52e098b6f assets/refinedstorage/models/item/blue_network_transmitter.json 8053c22618e7d51150fab4172a1cb2e3c9d36b4c assets/refinedstorage/models/item/blue_pattern_grid.json 763ebca22b3642be09f396deac9cd9c54b90e58f assets/refinedstorage/models/item/blue_relay.json 5abbfde1e5a947ae44fde121c3294f9fb2b60e7d assets/refinedstorage/models/item/blue_security_manager.json e38c127e67a2ef649d7ed595577947c93473d3d2 assets/refinedstorage/models/item/blue_wireless_transmitter.json f27acd12556251b68e10d33d55cb90bcee40ab07 assets/refinedstorage/models/item/brown_controller.json 0fb2cc9e3e05d19d9fcc5e04c6baeaa2cb04265c assets/refinedstorage/models/item/brown_crafter.json 022322ce32ac742f4ce5498d3da128741fe0767d assets/refinedstorage/models/item/brown_crafter_manager.json eb37e649bbb3f087df69a30c22215418b3fc901d assets/refinedstorage/models/item/brown_crafting_grid.json 4556f504e89f87de6ab73c12259b73eb151e8d7a assets/refinedstorage/models/item/brown_crafting_monitor.json f27acd12556251b68e10d33d55cb90bcee40ab07 assets/refinedstorage/models/item/brown_creative_controller.json 470afaeaaaec68a1474b2efcb2e027382b6d4069 assets/refinedstorage/models/item/brown_detector.json 12c9098c38f118056d9576671287b9783e50be98 assets/refinedstorage/models/item/brown_disk_manipulator.json 7fcf4b0092b4a6e733046548217f8cd40a0b0c01 assets/refinedstorage/models/item/brown_fluid_grid.json 67016265a1d6961ef06211484795a61cc310e6b4 assets/refinedstorage/models/item/brown_grid.json db89e452a0539344eafd946085a171bfd104a9cd assets/refinedstorage/models/item/brown_network_receiver.json 293b7ae86745d49806b8cf07d9f7f3fb900129f8 assets/refinedstorage/models/item/brown_network_transmitter.json a852eda91b130409a8127af77cf1a00b2aab81c8 assets/refinedstorage/models/item/brown_pattern_grid.json 023fb3d3d0164e237d6d8c83028e66ffb080905f assets/refinedstorage/models/item/brown_relay.json 45c70a18a9b27b3a0f7cd41a450ba23ba4b97faf assets/refinedstorage/models/item/brown_security_manager.json 3c329581c36a66b21409184843a78e90eae25c50 assets/refinedstorage/models/item/brown_wireless_transmitter.json 9af89e77d470eaf03b34847b568e0fcd0cfeb2ca assets/refinedstorage/models/item/controller.json 712a2408676f6ce1208b196d0cfe065136d612fe assets/refinedstorage/models/item/crafter.json 2adb1c2ed2c30890df2492069293f20c085eddf2 assets/refinedstorage/models/item/crafter_manager.json 2ef1da280a960eafd61369b67ea1647966fdcc0c assets/refinedstorage/models/item/crafting_grid.json ea61beccbf6896f3fdf99b8d4787be67573595dc assets/refinedstorage/models/item/crafting_monitor.json 9af89e77d470eaf03b34847b568e0fcd0cfeb2ca assets/refinedstorage/models/item/creative_controller.json d3d25cbac485889dd6766253c3fb96a1827963a9 assets/refinedstorage/models/item/cyan_controller.json 5b3089cc0257509445e335427fcee15a0c6d19e4 assets/refinedstorage/models/item/cyan_crafter.json 734e1865d2b25eda65d72541f7db30b277d3cf73 assets/refinedstorage/models/item/cyan_crafter_manager.json c4fc9d67c903d107548d25237173d1df0dfad2ee assets/refinedstorage/models/item/cyan_crafting_grid.json 133a84e4fd76123350bffc37cab6156ae6a0f61f assets/refinedstorage/models/item/cyan_crafting_monitor.json d3d25cbac485889dd6766253c3fb96a1827963a9 assets/refinedstorage/models/item/cyan_creative_controller.json 3e224af44dddb95f804967974a776f3d39e14f79 assets/refinedstorage/models/item/cyan_detector.json db51d1db8c2ef34f4ca03499081995031fc9bd75 assets/refinedstorage/models/item/cyan_disk_manipulator.json 959e0627277816d1d5a0a529bee59631aa2cbd59 assets/refinedstorage/models/item/cyan_fluid_grid.json 5e4dec30d4dffc887cd8e8b967ca0d43e5f53d18 assets/refinedstorage/models/item/cyan_grid.json eb2db4269ca283c9665b9fa5e1235862af32b000 assets/refinedstorage/models/item/cyan_network_receiver.json 6a5dfd3fc40fda27327da49c895775099d0406bb assets/refinedstorage/models/item/cyan_network_transmitter.json f404bf86051e76eb736827ecb9a7acbb78a86a0c assets/refinedstorage/models/item/cyan_pattern_grid.json 2c6119b52833d26535d5c9c826f806b1a799745c assets/refinedstorage/models/item/cyan_relay.json c3bcb743cd9b551b8e3e07dd16a039ccce65167f assets/refinedstorage/models/item/cyan_security_manager.json 9ab085f44867d2c6e6431914ee0b8d5b20f1f6ea assets/refinedstorage/models/item/cyan_wireless_transmitter.json a14c5f121b112f80f018eb39e4017a044f5176c2 assets/refinedstorage/models/item/detector.json b864dd2a574cb0ff0f87373ba145b7e7c4b6a315 assets/refinedstorage/models/item/disk_manipulator.json b6f77a02dc8f84c8dc50af0e3ca8d4a2597894fb assets/refinedstorage/models/item/fluid_grid.json 2793400d4b735f12ca00a38d89ce230de4882728 assets/refinedstorage/models/item/gray_controller.json f201a4dc689054fbf5afa4cd9318059b45e34fac assets/refinedstorage/models/item/gray_crafter.json d699ea44dc8ba183d453f865bb5dd816cae8a628 assets/refinedstorage/models/item/gray_crafter_manager.json e8beb5658c198903aa882e818e9f1a12fb219ed2 assets/refinedstorage/models/item/gray_crafting_grid.json a24b4fb9353df1c8b9ba48ec7cda1402a0d18e06 assets/refinedstorage/models/item/gray_crafting_monitor.json 2793400d4b735f12ca00a38d89ce230de4882728 assets/refinedstorage/models/item/gray_creative_controller.json 3a62caa71a381e853fb8e1fd09e6eca16de95b8c assets/refinedstorage/models/item/gray_detector.json 876cf3b8ad044945e93a2dcf595e5ee851a95801 assets/refinedstorage/models/item/gray_disk_manipulator.json 4eb03c2834f4d92be29707d3a7e3412d2e5afae7 assets/refinedstorage/models/item/gray_fluid_grid.json 1ba67cee521c3d178eae56d0ee44c13dc244ecc6 assets/refinedstorage/models/item/gray_grid.json dd9a85970dd5e0f4f7f0da196cda01b3f1156007 assets/refinedstorage/models/item/gray_network_receiver.json d549169a533feee23ee8f3e1b39b7c4bcf23b475 assets/refinedstorage/models/item/gray_network_transmitter.json 558bee5f5c8415c73aae98e67851e9f192ab7157 assets/refinedstorage/models/item/gray_pattern_grid.json 39bd74ec45ffe304d1e339d184b2164117d88b5f assets/refinedstorage/models/item/gray_relay.json 9db80d9e795dbe5edff7a565671cf0095a7c4973 assets/refinedstorage/models/item/gray_security_manager.json be60c25b51488e5a1f5db9aa0b8ce834b4f843b6 assets/refinedstorage/models/item/gray_wireless_transmitter.json a6dccc5437fa6c15a9a032e7862c4c5653849dd8 assets/refinedstorage/models/item/green_controller.json 36aec4f5a603dddd1817a815a612a4eb7190e222 assets/refinedstorage/models/item/green_crafter.json 6fce1c029999c014a5d9bd0ac7b2b24838dc0cf6 assets/refinedstorage/models/item/green_crafter_manager.json 3d835f157f4ace96a84a0e990276fe03fe1758c4 assets/refinedstorage/models/item/green_crafting_grid.json cbb61098395bda16b743c82f56529a00d91a708a assets/refinedstorage/models/item/green_crafting_monitor.json a6dccc5437fa6c15a9a032e7862c4c5653849dd8 assets/refinedstorage/models/item/green_creative_controller.json 7ec5ba813db5c1ae5663bebfa659b53c8e75096c assets/refinedstorage/models/item/green_detector.json 7b0b74419933a23e3921672b49edc8830d1b3045 assets/refinedstorage/models/item/green_disk_manipulator.json a8c70489b145ecafc07040195946c329ae30da41 assets/refinedstorage/models/item/green_fluid_grid.json 5e5828f3f71c072a6b5aea5d219123eb392fb7b3 assets/refinedstorage/models/item/green_grid.json a0b8687000680d8d8a55a7d6e21a6a5b8c3ba935 assets/refinedstorage/models/item/green_network_receiver.json 9be69ecfb8d48aa8b7a1dfe97e428ab50b261864 assets/refinedstorage/models/item/green_network_transmitter.json ffa8411a90dd0a79f72936c46b1514340c561fdc assets/refinedstorage/models/item/green_pattern_grid.json ca9981a8b7c74fbdea91c12409b1c56929f829a2 assets/refinedstorage/models/item/green_relay.json 29860d74f6f59ebabc4534eb3e437c50d82e6d75 assets/refinedstorage/models/item/green_security_manager.json 0f626e543261b13e2d9021d09fc804236b9c9ca5 assets/refinedstorage/models/item/green_wireless_transmitter.json 8e62b1170a93f317a3a0463eb2dc331bc6a29fc8 assets/refinedstorage/models/item/grid.json dbcc2e910fd5029dd5061fc018b0c21bee0aa0b0 assets/refinedstorage/models/item/light_gray_controller.json 1280d243a5ee781a911776123a92280f6871e92b assets/refinedstorage/models/item/light_gray_crafter.json 63d91aa91f0b04bc56661d77cba3802a028b14c3 assets/refinedstorage/models/item/light_gray_crafter_manager.json 5447f9412ac89a2453495f7012906936556f3f97 assets/refinedstorage/models/item/light_gray_crafting_grid.json 589f1eab82f17738f7c84408250051526612166c assets/refinedstorage/models/item/light_gray_crafting_monitor.json dbcc2e910fd5029dd5061fc018b0c21bee0aa0b0 assets/refinedstorage/models/item/light_gray_creative_controller.json c0fe9601a0b96cb28e05777646e8b1fa06dff11c assets/refinedstorage/models/item/light_gray_detector.json a015d9065f13234987d35e242922e19a39cda358 assets/refinedstorage/models/item/light_gray_disk_manipulator.json 792b2649c17462ffad43035187f9ae62faf2f741 assets/refinedstorage/models/item/light_gray_fluid_grid.json 7a93c48e5851c4d45de5a6d138c16556faee7090 assets/refinedstorage/models/item/light_gray_grid.json d7492fb5ea426b156d29d90cac3c068a69257993 assets/refinedstorage/models/item/light_gray_network_receiver.json 180ce6ef10d59c8495a35a00dd05ba68011f0238 assets/refinedstorage/models/item/light_gray_network_transmitter.json 0574aa946a4db136d2141b599587b5e06b4cb5f4 assets/refinedstorage/models/item/light_gray_pattern_grid.json 4b04ebd4de4cc44d66f69595a15e19c986bd89c5 assets/refinedstorage/models/item/light_gray_relay.json 72c8be165eead23444e70fd27b214fbe4b4c8f5c assets/refinedstorage/models/item/light_gray_security_manager.json cf8a25b86388ed35135d6f7abc84c9db2f8c3147 assets/refinedstorage/models/item/light_gray_wireless_transmitter.json 191c24b9824b3c218963d8ec68c79a25600cd04e assets/refinedstorage/models/item/lime_controller.json b5fe18a5faa8b19bca2356055bed26e3c4b7d6da assets/refinedstorage/models/item/lime_crafter.json c06a4c91f48f582ec7bbddf1992632496f628052 assets/refinedstorage/models/item/lime_crafter_manager.json 5cd081548f10fccc38406afa4e62211a67068868 assets/refinedstorage/models/item/lime_crafting_grid.json d42a9b602a6b3e8ca87f44093bd5dbb8d025b83b assets/refinedstorage/models/item/lime_crafting_monitor.json 191c24b9824b3c218963d8ec68c79a25600cd04e assets/refinedstorage/models/item/lime_creative_controller.json acc983f06040f4785c84fca542678df7bf93eba6 assets/refinedstorage/models/item/lime_detector.json 19e1e36a546b3ec487a2a4356d85b0f0d72ad69d assets/refinedstorage/models/item/lime_disk_manipulator.json 2d485286e0757a593ca7ce9cd37ce34ba036fc4f assets/refinedstorage/models/item/lime_fluid_grid.json 16d5987ef2c508c6ce6c4b06d79d34ae5e43a985 assets/refinedstorage/models/item/lime_grid.json 2bca4fdbc24291df49aed6c594df508b01b32a24 assets/refinedstorage/models/item/lime_network_receiver.json a9be76a8a262a6a315f1227d33c8d7304b21f04a assets/refinedstorage/models/item/lime_network_transmitter.json 9c3504533314ded4447251d7321f662e651587f7 assets/refinedstorage/models/item/lime_pattern_grid.json 95676494b1360458129336fb1c89a827d9887d9a assets/refinedstorage/models/item/lime_relay.json c06aaadeb1e8573ee6a8f4d66c47a908df9df070 assets/refinedstorage/models/item/lime_security_manager.json 4ac21895d402f5824f599daeae315330deeeb5cc assets/refinedstorage/models/item/lime_wireless_transmitter.json ed8cd700afa7ce785453398f1739fa69b544306b assets/refinedstorage/models/item/magenta_controller.json 7ae69165d5905f17a5e837de77d22941f3f22181 assets/refinedstorage/models/item/magenta_crafter.json 97a0c41ddb54000647c33b56095215033b7f364a assets/refinedstorage/models/item/magenta_crafter_manager.json fea6df9eea90ca27131d5b9e37b08d50b1cb3618 assets/refinedstorage/models/item/magenta_crafting_grid.json 3bf88ca8bbd2ebe7eba52cd6a90a81d4af0391b0 assets/refinedstorage/models/item/magenta_crafting_monitor.json ed8cd700afa7ce785453398f1739fa69b544306b assets/refinedstorage/models/item/magenta_creative_controller.json 5fdee8b4342e1b1b8e09a8ab300fcb9dbdcf8530 assets/refinedstorage/models/item/magenta_detector.json 44ff4ad0e90b6b4bc72653d833e04e5352241304 assets/refinedstorage/models/item/magenta_disk_manipulator.json 220ab0b014958d16917799de11a951e9ab8b207c assets/refinedstorage/models/item/magenta_fluid_grid.json 8e3ea806407ae7ec6dd0619f8bdb2edf0c6fe0aa assets/refinedstorage/models/item/magenta_grid.json 89da8c0449d5c16adbf793f08fa64e78ad320018 assets/refinedstorage/models/item/magenta_network_receiver.json 6228fdb00897e8e25454017336570fe15410ee4c assets/refinedstorage/models/item/magenta_network_transmitter.json 1aeb5a567564f664893434a89d95c640006c3d0e assets/refinedstorage/models/item/magenta_pattern_grid.json 7cde3959bc32026f58cdc12755d1c9ecedb74f51 assets/refinedstorage/models/item/magenta_relay.json d7bcf381a5d9689d554438184f0fec0012f65f05 assets/refinedstorage/models/item/magenta_security_manager.json 833c0a8c3e209c604cad8146468143470693f42a assets/refinedstorage/models/item/magenta_wireless_transmitter.json 6dbbe55fd346aaa8eec23b2808ffd18d5840d832 assets/refinedstorage/models/item/network_receiver.json 54f8841b6832f05b8e5076cfb5a714ef66c4b159 assets/refinedstorage/models/item/network_transmitter.json 62a9e346d5e83e3b4c1c947d7ef5316d93b168a6 assets/refinedstorage/models/item/orange_controller.json 2a934a32a43fd58110eebc7b3e4b05f71c21b76c assets/refinedstorage/models/item/orange_crafter.json 3e7fbb114a1270c3e2cf2d79f043c62e869de2dc assets/refinedstorage/models/item/orange_crafter_manager.json 4f35a7cc88dff4dc4ee066261024f14f123f8227 assets/refinedstorage/models/item/orange_crafting_grid.json 0c7188e1968be58e1797720861a5d104f7dae2a4 assets/refinedstorage/models/item/orange_crafting_monitor.json 62a9e346d5e83e3b4c1c947d7ef5316d93b168a6 assets/refinedstorage/models/item/orange_creative_controller.json 833cc370275e91e9088bba3505b52e9199beafca assets/refinedstorage/models/item/orange_detector.json cc94b04311c3c1089dc1e488464540f5ef04b448 assets/refinedstorage/models/item/orange_disk_manipulator.json 846a0e2b574b4518a392916902564fc692b72994 assets/refinedstorage/models/item/orange_fluid_grid.json 862b3b4e3b1eaddb034cb8b4384c1cf7374a0778 assets/refinedstorage/models/item/orange_grid.json 7d58c259c555a33cad472a3edfc3bd33f4160c66 assets/refinedstorage/models/item/orange_network_receiver.json 0e1f7e25ce5bbc1369116550f3f7c095cff3df12 assets/refinedstorage/models/item/orange_network_transmitter.json cae021973ae73db4f26907bc20af071b4788a7d1 assets/refinedstorage/models/item/orange_pattern_grid.json 8dab67d1e96096cdc41c4b62dcabfd81019b518c assets/refinedstorage/models/item/orange_relay.json fc333d59e066c62ef6bad598dfaadcc030655f23 assets/refinedstorage/models/item/orange_security_manager.json 27557f3fd10361a51c867fe8211073807576f040 assets/refinedstorage/models/item/orange_wireless_transmitter.json 4368418d5b92cbaa041d20e6f25d06ab3f24fd6f assets/refinedstorage/models/item/pattern_grid.json 0514638803a2e3805e5078001fb4f53ceb7d1a41 assets/refinedstorage/models/item/pink_controller.json 3b472cd0ed96b6eb64c7695429cc7a76e629f1a6 assets/refinedstorage/models/item/pink_crafter.json 03a29baf74da2cbf3d7ee5ae8d9925d19c34e8f3 assets/refinedstorage/models/item/pink_crafter_manager.json e0710739ed2c8c74147585c990fe62d9fdb18ab0 assets/refinedstorage/models/item/pink_crafting_grid.json 71045a36761dca453325aced8d84cff206c81817 assets/refinedstorage/models/item/pink_crafting_monitor.json 0514638803a2e3805e5078001fb4f53ceb7d1a41 assets/refinedstorage/models/item/pink_creative_controller.json 6c67a4fc7796172f625c4862cf616c86bf8cba79 assets/refinedstorage/models/item/pink_detector.json 75c748b9473e195554615573406e1571b5ccac10 assets/refinedstorage/models/item/pink_disk_manipulator.json c3b2796d126d95f9141472a0c0009d88bd7cb855 assets/refinedstorage/models/item/pink_fluid_grid.json 9af67ec1885b0215227dcd252606a5893eb04302 assets/refinedstorage/models/item/pink_grid.json b376b5e220c3ae55cf3ecfb69495d57b554f9223 assets/refinedstorage/models/item/pink_network_receiver.json ba12ed9891fa73b2336ff93ab4bfd0d3b1492652 assets/refinedstorage/models/item/pink_network_transmitter.json 869f05efe6e5d262b6094b68913c99472c11895d assets/refinedstorage/models/item/pink_pattern_grid.json 6d6d9cd242688e2891cd6fc8c74eb19dcf36ac19 assets/refinedstorage/models/item/pink_relay.json fe2fc6e128f619dddc5d9f04486264a245c2b457 assets/refinedstorage/models/item/pink_security_manager.json 332f608a7dc84019b8b0fa2a5e44ad9f78e430de assets/refinedstorage/models/item/pink_wireless_transmitter.json 0f11e9205719c6fe582e96bd4205ac7c93bfd209 assets/refinedstorage/models/item/purple_controller.json 506b89f03df977db6eb43c09d39b8aa8d7fcc28a assets/refinedstorage/models/item/purple_crafter.json b3b6be54491ba314822a6b47b20a55955b81a986 assets/refinedstorage/models/item/purple_crafter_manager.json 413fffa72205e3c3f50106162bf88e8d18cad8ab assets/refinedstorage/models/item/purple_crafting_grid.json ac159f10aab33c9e95009384d994a46caf4e9c5b assets/refinedstorage/models/item/purple_crafting_monitor.json 0f11e9205719c6fe582e96bd4205ac7c93bfd209 assets/refinedstorage/models/item/purple_creative_controller.json a137fc45d5f9b891ef00d75a2855258a88177668 assets/refinedstorage/models/item/purple_detector.json 525576087501ad8483619e8339a614951eada2b6 assets/refinedstorage/models/item/purple_disk_manipulator.json 80fb0c7bc38471d990c1623918a96db182bbe93b assets/refinedstorage/models/item/purple_fluid_grid.json 87e4943c1c019cac11083c479a4c5f563051ddd2 assets/refinedstorage/models/item/purple_grid.json f319ca93c15a56a7927d022c123608dfb1a91f21 assets/refinedstorage/models/item/purple_network_receiver.json 46eb95a94c5d12503bcfbcdaf849a03a176974b9 assets/refinedstorage/models/item/purple_network_transmitter.json c5a01a9ddace2e421e32b12c83d7a0b384be75fa assets/refinedstorage/models/item/purple_pattern_grid.json e2efaf0e99c7dc1125b32370201be809a67c25d9 assets/refinedstorage/models/item/purple_relay.json 3c3ed303d605e0e9345940fc1756e2ecd1c48287 assets/refinedstorage/models/item/purple_security_manager.json ef7d480ea1f08c1a2a7c2aebcbe3ca751df9f9b6 assets/refinedstorage/models/item/purple_wireless_transmitter.json 004e6cf370c1b7ad3d243a358494bb1af2fdee8d assets/refinedstorage/models/item/red_controller.json 6804c531235f5c7cd13f0c734a30aa58855c66d8 assets/refinedstorage/models/item/red_crafter.json f2804c202120637bff89dd8b2ab8e43ba1f5aafc assets/refinedstorage/models/item/red_crafter_manager.json acddcd41152a23916905fd85ad62081f5cb8c90c assets/refinedstorage/models/item/red_crafting_grid.json 5a93d02b15f7ef2d9803ef0d004930ed1766707b assets/refinedstorage/models/item/red_crafting_monitor.json 004e6cf370c1b7ad3d243a358494bb1af2fdee8d assets/refinedstorage/models/item/red_creative_controller.json 4c1c2a7322dada203e2521225d80c5b516cacb62 assets/refinedstorage/models/item/red_detector.json 262bdaf7a4a2a587dc88e3fb5c72c22e16829998 assets/refinedstorage/models/item/red_disk_manipulator.json 67e092b9a6df25cb4396d3ae4464dd3c009c60b2 assets/refinedstorage/models/item/red_fluid_grid.json beb09fb2b90d4a5d0e2debb2b496f7cc5e1906af assets/refinedstorage/models/item/red_grid.json c2f491455989b852e1c40a2e2003aeb482b5a628 assets/refinedstorage/models/item/red_network_receiver.json d2127558a02a6cb0a6c58a1feb8a4b9eb251d544 assets/refinedstorage/models/item/red_network_transmitter.json 591164ab827c9f7fd0cfa0f7e7b42c94f801fac6 assets/refinedstorage/models/item/red_pattern_grid.json 4eaa387e037be30d51852c185d80ee1eea03559f assets/refinedstorage/models/item/red_relay.json 37b2c3f4b626765fb97a1aada4c0cc5b60ffac67 assets/refinedstorage/models/item/red_security_manager.json 05e22d0e5fafbbe8c6864c896a05907b1808c4cf assets/refinedstorage/models/item/red_wireless_transmitter.json 58e008aea088a9e1903885a2bc6e14d9f0b2c333 assets/refinedstorage/models/item/relay.json e0546ec6993e456e7ef61a35cccc862382b15fd5 assets/refinedstorage/models/item/security_manager.json 9b37576964ccce28c9396299400a78a0a9d9ee04 assets/refinedstorage/models/item/white_controller.json c6e5a16319d0fad19ac8ede0108b658cd4028146 assets/refinedstorage/models/item/white_crafter.json e6194df137b2c614d6402d6dc672beae80430d38 assets/refinedstorage/models/item/white_crafter_manager.json 399926c00694fa7abefd1709cc3da37d7eb0c5af assets/refinedstorage/models/item/white_crafting_grid.json ecff06abfe1465fb6630f027f9253965ceb2ed60 assets/refinedstorage/models/item/white_crafting_monitor.json 9b37576964ccce28c9396299400a78a0a9d9ee04 assets/refinedstorage/models/item/white_creative_controller.json 5f1ae8346d30d2e4f6b5aed97504d35ec05eecfe assets/refinedstorage/models/item/white_detector.json 0eec3932d36ed9e265a48b90fc1ae83bb95a3aa3 assets/refinedstorage/models/item/white_disk_manipulator.json ca0c7707acf771758db0194f30f1247d4721ae50 assets/refinedstorage/models/item/white_fluid_grid.json 42e10b1a94e013425fc1ff146d9cdc07c4b242b4 assets/refinedstorage/models/item/white_grid.json 39d06d08ba1e35d8322386345828d14eb16ac0d8 assets/refinedstorage/models/item/white_network_receiver.json 4c147f69e564648441aaeecee3c2fc132501fc05 assets/refinedstorage/models/item/white_network_transmitter.json 6a4add44bd9ff08a7d30fc79d38c45f9f9aa55da assets/refinedstorage/models/item/white_pattern_grid.json 8fc4acd3d401ce6496db2af111ab2b97716349bf assets/refinedstorage/models/item/white_relay.json 42c146254c8c634eb9f79f29b909535b0504d6a5 assets/refinedstorage/models/item/white_security_manager.json dffc5e13406d4370d1cc3fcc69c7556029406e98 assets/refinedstorage/models/item/white_wireless_transmitter.json 08797906f5356ea0ccc061347d188bab0c63c02d assets/refinedstorage/models/item/wireless_transmitter.json 2fca7b8b45c98bc01de598dd53f0f80f2e547dd4 assets/refinedstorage/models/item/yellow_controller.json 1bf5a3d8d72edcd34ddf8266caaac89717a02ecb assets/refinedstorage/models/item/yellow_crafter.json 6b33ac9d2c729a4ea8dd42efb8feeb553a434d70 assets/refinedstorage/models/item/yellow_crafter_manager.json b628289d264ed316cd2d88c297fb8712f8bbffd2 assets/refinedstorage/models/item/yellow_crafting_grid.json 496e7503c51cf826e718301641235d07ddb24de7 assets/refinedstorage/models/item/yellow_crafting_monitor.json 2fca7b8b45c98bc01de598dd53f0f80f2e547dd4 assets/refinedstorage/models/item/yellow_creative_controller.json 04e4c31f56373507a46da2deccc4890305fe671e assets/refinedstorage/models/item/yellow_detector.json 6412b4000a8034e4b5e019b9a6d9c32085cda263 assets/refinedstorage/models/item/yellow_disk_manipulator.json 5b6b9685ed940cdfcede5c4df4b6836fbd748895 assets/refinedstorage/models/item/yellow_fluid_grid.json bf3386182b6e8b29a9e4e8f72eaeec17169a39e5 assets/refinedstorage/models/item/yellow_grid.json e0283cdc201bd14bf272859692be8f71c0f9cbeb assets/refinedstorage/models/item/yellow_network_receiver.json 29a2c43527626231f73d53badc08a9f6f11f7615 assets/refinedstorage/models/item/yellow_network_transmitter.json b9bfe30d83136faf826f2391fb7a3ed3742ae22e assets/refinedstorage/models/item/yellow_pattern_grid.json bd7660f94971400544ee3ea14876efab3f493b96 assets/refinedstorage/models/item/yellow_relay.json fc534d01e53b660bf69498968487d1dae1b6de02 assets/refinedstorage/models/item/yellow_security_manager.json e6c24f334bd8249c5c629b86fc761d92d9f901e5 assets/refinedstorage/models/item/yellow_wireless_transmitter.json ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/black", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/black", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/black", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/black", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/black" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/black", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/black" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/black", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/black" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/black", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/black", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/black_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/black" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/black", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/black", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/black", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/black", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/black", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/blue", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/blue", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/blue", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/blue", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/blue" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/blue", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/blue_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/blue" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/blue", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/blue", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/blue", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/blue", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/blue", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/brown", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/brown", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/brown", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/brown", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/brown" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/brown", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/brown" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/brown", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/brown" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/brown", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/brown", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/brown_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/brown" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/brown", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/brown", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/brown", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/brown", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/brown", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/light_blue", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/light_blue", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/light_blue", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/light_blue", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/light_blue" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/light_blue", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/cyan", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/cyan", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/cyan", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/cyan", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/cyan" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/cyan", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/cyan" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/cyan", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/cyan" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/cyan", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/cyan", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/cyan_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/cyan" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/cyan", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/cyan", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/cyan", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/cyan", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/cyan", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/gray", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/gray", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/gray", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/gray", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/gray" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/gray", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/gray_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/gray" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/gray", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/gray", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/gray", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/gray", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/gray", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/green", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/green", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/green", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/green", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/green" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/green", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/green" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/green", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/green" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/green", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/green", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/green_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/green" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/green", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/green", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/green", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/green", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/green", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/light_gray", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/light_gray", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/light_gray", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/light_gray", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/light_gray" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/light_gray", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/light_gray" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/light_gray", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/light_gray" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/light_gray", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/light_gray", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/light_gray_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/light_gray" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/light_gray", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/light_gray", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/light_gray", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/light_gray", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/light_gray", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/lime", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/lime", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/lime", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/lime", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/lime" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/lime", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/lime" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/lime", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/lime" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/lime", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/lime", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/lime_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/lime" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/lime", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/lime", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/lime", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/lime", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/lime", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/magenta", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/magenta", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/magenta", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/magenta", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/magenta" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/magenta", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/magenta" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/magenta", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/magenta" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/magenta", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/magenta", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/magenta_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/magenta" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/magenta", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/magenta", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/magenta", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/magenta", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/magenta", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/orange", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/orange", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/orange", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/orange", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/orange" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/orange", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/orange" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/orange", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/orange" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/orange", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/orange", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/orange_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/orange" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/orange", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/orange", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/orange", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/orange", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/orange", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/pink", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/pink", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/pink", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/pink", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/pink" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/pink", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/pink" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/pink", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/pink" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/pink", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/pink", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/pink_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/pink" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/pink", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/pink", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/pink", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/pink", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/pink", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/purple", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/purple", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/purple", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/purple", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/purple" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/purple", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/purple" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/purple", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/purple" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/purple", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/purple", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/purple_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/purple" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/purple", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/purple", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/purple", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/purple", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/purple", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/red", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/red", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/red", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/red", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/red" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/red", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/red" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/red", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/red" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/red", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/red", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/red_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/red" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/red", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/red", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/red", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/red", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/red", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/light_blue" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/light_blue", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/light_blue" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/light_blue", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/light_blue", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/white", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/white", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/white", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/white", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/white" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/white", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/white" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/white", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/white" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/white", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/white", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/white_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/white" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/white", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/white", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/white", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/white", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/white", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/light_blue" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/light_blue", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/light_blue", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/light_blue", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/light_blue", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/light_blue", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_crafter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/crafter/disconnected", "x": 180 }, "connected=false,direction=east": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter/disconnected", "x": 90 }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=up": { "model": "refinedstorage:block/crafter/disconnected" }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter/disconnected", "x": 90, "y": 270 }, "connected=true,direction=down": { "model": "refinedstorage:block/crafter/yellow", "x": 180 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter/yellow", "x": 90, "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter/yellow", "x": 90 }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter/yellow", "x": 90, "y": 180 }, "connected=true,direction=up": { "model": "refinedstorage:block/crafter/yellow" }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter/yellow", "x": 90, "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_crafter_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafter_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafter_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafter_manager/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafter_manager/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafter_manager/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafter_manager/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_crafting_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_grid/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_grid/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_grid/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_grid/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_crafting_monitor.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/crafting_monitor/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/crafting_monitor/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/crafting_monitor/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/crafting_monitor/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/crafting_monitor/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/crafting_monitor/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_creative_controller.json ================================================ { "variants": { "energy_type=nearly_off": { "model": "refinedstorage:block/controller/nearly_off" }, "energy_type=nearly_on": { "model": "refinedstorage:block/controller/nearly_on" }, "energy_type=off": { "model": "refinedstorage:block/controller/off" }, "energy_type=on": { "model": "refinedstorage:block/controller/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_detector.json ================================================ { "variants": { "powered=false": { "model": "refinedstorage:block/detector/off" }, "powered=true": { "model": "refinedstorage:block/detector/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_disk_manipulator.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_manipulator/loader" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_fluid_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/fluid_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/fluid_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/fluid_grid/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/fluid_grid/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/fluid_grid/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/fluid_grid/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/grid/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/grid/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/grid/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/grid/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_network_receiver.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_receiver/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_receiver/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_network_transmitter.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/network_transmitter/disconnected" }, "connected=true": { "model": "refinedstorage:block/network_transmitter/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_pattern_grid.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/pattern_grid/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/pattern_grid/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/pattern_grid/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/pattern_grid/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/pattern_grid/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/pattern_grid/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_relay.json ================================================ { "variants": { "connected=false": { "model": "refinedstorage:block/relay/disconnected" }, "connected=true": { "model": "refinedstorage:block/relay/yellow" } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_security_manager.json ================================================ { "variants": { "connected=false,direction=east": { "model": "refinedstorage:block/security_manager/disconnected", "y": 90 }, "connected=false,direction=north": { "model": "refinedstorage:block/security_manager/disconnected" }, "connected=false,direction=south": { "model": "refinedstorage:block/security_manager/disconnected", "y": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/security_manager/disconnected", "y": 270 }, "connected=true,direction=east": { "model": "refinedstorage:block/security_manager/yellow", "y": 90 }, "connected=true,direction=north": { "model": "refinedstorage:block/security_manager/yellow" }, "connected=true,direction=south": { "model": "refinedstorage:block/security_manager/yellow", "y": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/security_manager/yellow", "y": 270 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/blockstates/yellow_wireless_transmitter.json ================================================ { "variants": { "connected=false,direction=down": { "model": "refinedstorage:block/wireless_transmitter/disconnected" }, "connected=false,direction=east": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 270 }, "connected=false,direction=north": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 180 }, "connected=false,direction=south": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90 }, "connected=false,direction=up": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 180 }, "connected=false,direction=west": { "model": "refinedstorage:block/wireless_transmitter/disconnected", "x": 90, "y": 90 }, "connected=true,direction=down": { "model": "refinedstorage:block/wireless_transmitter/yellow" }, "connected=true,direction=east": { "model": "refinedstorage:block/wireless_transmitter/yellow", "x": 90, "y": 270 }, "connected=true,direction=north": { "model": "refinedstorage:block/wireless_transmitter/yellow", "x": 90, "y": 180 }, "connected=true,direction=south": { "model": "refinedstorage:block/wireless_transmitter/yellow", "x": 90 }, "connected=true,direction=up": { "model": "refinedstorage:block/wireless_transmitter/yellow", "x": 180 }, "connected=true,direction=west": { "model": "refinedstorage:block/wireless_transmitter/yellow", "x": 90, "y": 90 } } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/black.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/black", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/blue", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/brown.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/brown", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/cyan.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/cyan", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/gray", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/green.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/green", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/light_blue", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/light_gray", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/lime.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/lime", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/magenta.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/magenta", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/nearly_off.json ================================================ { "parent": "refinedstorage:block/controller_nearly", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/nearly_off_gray", "cutout_gray": "refinedstorage:block/controller/cutouts/nearly_off", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/nearly_on.json ================================================ { "parent": "refinedstorage:block/controller_nearly", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/nearly_on_gray", "cutout_gray": "refinedstorage:block/controller/cutouts/nearly_on", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/off.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout_nonemissive", "textures": { "all": "refinedstorage:block/controller/off", "cutout": "refinedstorage:block/controller/cutouts/off", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/orange.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/orange", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/pink.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/pink", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/purple.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/purple", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/red.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/red", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/white.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/white", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/controller/yellow.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/controller/on", "cutout": "refinedstorage:block/controller/cutouts/yellow", "particle": "refinedstorage:block/controller/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/black.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_black", "cutout_north": "refinedstorage:block/crafter/cutouts/side_black", "cutout_south": "refinedstorage:block/crafter/cutouts/side_black", "cutout_up": "refinedstorage:block/crafter/cutouts/top_black", "cutout_west": "refinedstorage:block/crafter/cutouts/side_black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/blue.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_blue", "cutout_north": "refinedstorage:block/crafter/cutouts/side_blue", "cutout_south": "refinedstorage:block/crafter/cutouts/side_blue", "cutout_up": "refinedstorage:block/crafter/cutouts/top_blue", "cutout_west": "refinedstorage:block/crafter/cutouts/side_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/brown.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_brown", "cutout_north": "refinedstorage:block/crafter/cutouts/side_brown", "cutout_south": "refinedstorage:block/crafter/cutouts/side_brown", "cutout_up": "refinedstorage:block/crafter/cutouts/top_brown", "cutout_west": "refinedstorage:block/crafter/cutouts/side_brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/cyan.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_cyan", "cutout_north": "refinedstorage:block/crafter/cutouts/side_cyan", "cutout_south": "refinedstorage:block/crafter/cutouts/side_cyan", "cutout_up": "refinedstorage:block/crafter/cutouts/top_cyan", "cutout_west": "refinedstorage:block/crafter/cutouts/side_cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_cutout_nonemissive", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_disconnected", "cutout_north": "refinedstorage:block/crafter/cutouts/side_disconnected", "cutout_south": "refinedstorage:block/crafter/cutouts/side_disconnected", "cutout_up": "refinedstorage:block/crafter/cutouts/top_disconnected", "cutout_west": "refinedstorage:block/crafter/cutouts/side_disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/gray.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_gray", "cutout_north": "refinedstorage:block/crafter/cutouts/side_gray", "cutout_south": "refinedstorage:block/crafter/cutouts/side_gray", "cutout_up": "refinedstorage:block/crafter/cutouts/top_gray", "cutout_west": "refinedstorage:block/crafter/cutouts/side_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/green.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_green", "cutout_north": "refinedstorage:block/crafter/cutouts/side_green", "cutout_south": "refinedstorage:block/crafter/cutouts/side_green", "cutout_up": "refinedstorage:block/crafter/cutouts/top_green", "cutout_west": "refinedstorage:block/crafter/cutouts/side_green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_light_blue", "cutout_north": "refinedstorage:block/crafter/cutouts/side_light_blue", "cutout_south": "refinedstorage:block/crafter/cutouts/side_light_blue", "cutout_up": "refinedstorage:block/crafter/cutouts/top_light_blue", "cutout_west": "refinedstorage:block/crafter/cutouts/side_light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_light_gray", "cutout_north": "refinedstorage:block/crafter/cutouts/side_light_gray", "cutout_south": "refinedstorage:block/crafter/cutouts/side_light_gray", "cutout_up": "refinedstorage:block/crafter/cutouts/top_light_gray", "cutout_west": "refinedstorage:block/crafter/cutouts/side_light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/lime.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_lime", "cutout_north": "refinedstorage:block/crafter/cutouts/side_lime", "cutout_south": "refinedstorage:block/crafter/cutouts/side_lime", "cutout_up": "refinedstorage:block/crafter/cutouts/top_lime", "cutout_west": "refinedstorage:block/crafter/cutouts/side_lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/magenta.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_magenta", "cutout_north": "refinedstorage:block/crafter/cutouts/side_magenta", "cutout_south": "refinedstorage:block/crafter/cutouts/side_magenta", "cutout_up": "refinedstorage:block/crafter/cutouts/top_magenta", "cutout_west": "refinedstorage:block/crafter/cutouts/side_magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/orange.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_orange", "cutout_north": "refinedstorage:block/crafter/cutouts/side_orange", "cutout_south": "refinedstorage:block/crafter/cutouts/side_orange", "cutout_up": "refinedstorage:block/crafter/cutouts/top_orange", "cutout_west": "refinedstorage:block/crafter/cutouts/side_orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/pink.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_pink", "cutout_north": "refinedstorage:block/crafter/cutouts/side_pink", "cutout_south": "refinedstorage:block/crafter/cutouts/side_pink", "cutout_up": "refinedstorage:block/crafter/cutouts/top_pink", "cutout_west": "refinedstorage:block/crafter/cutouts/side_pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/purple.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_purple", "cutout_north": "refinedstorage:block/crafter/cutouts/side_purple", "cutout_south": "refinedstorage:block/crafter/cutouts/side_purple", "cutout_up": "refinedstorage:block/crafter/cutouts/top_purple", "cutout_west": "refinedstorage:block/crafter/cutouts/side_purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/red.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_red", "cutout_north": "refinedstorage:block/crafter/cutouts/side_red", "cutout_south": "refinedstorage:block/crafter/cutouts/side_red", "cutout_up": "refinedstorage:block/crafter/cutouts/top_red", "cutout_west": "refinedstorage:block/crafter/cutouts/side_red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/white.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_white", "cutout_north": "refinedstorage:block/crafter/cutouts/side_white", "cutout_south": "refinedstorage:block/crafter/cutouts/side_white", "cutout_up": "refinedstorage:block/crafter/cutouts/top_white", "cutout_west": "refinedstorage:block/crafter/cutouts/side_white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter/yellow.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/crafter/cutouts/side_yellow", "cutout_north": "refinedstorage:block/crafter/cutouts/side_yellow", "cutout_south": "refinedstorage:block/crafter/cutouts/side_yellow", "cutout_up": "refinedstorage:block/crafter/cutouts/top_yellow", "cutout_west": "refinedstorage:block/crafter/cutouts/side_yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter/side", "north": "refinedstorage:block/crafter/side", "particle": "refinedstorage:block/crafter/side", "south": "refinedstorage:block/crafter/side", "up": "refinedstorage:block/crafter/top", "west": "refinedstorage:block/crafter/side" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafter_manager/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafter_manager/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafter_manager/right", "north": "refinedstorage:block/crafter_manager/front", "particle": "refinedstorage:block/crafter_manager/right", "south": "refinedstorage:block/crafter_manager/back", "up": "refinedstorage:block/crafter_manager/top", "west": "refinedstorage:block/crafter_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_grid/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_grid/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_grid/right", "north": "refinedstorage:block/crafting_grid/front", "particle": "refinedstorage:block/crafting_grid/right", "south": "refinedstorage:block/crafting_grid/back", "up": "refinedstorage:block/crafting_grid/top", "west": "refinedstorage:block/crafting_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/crafting_monitor/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/crafting_monitor/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/crafting_monitor/right", "north": "refinedstorage:block/crafting_monitor/front", "particle": "refinedstorage:block/crafting_monitor/right", "south": "refinedstorage:block/crafting_monitor/back", "up": "refinedstorage:block/crafting_monitor/top", "west": "refinedstorage:block/crafting_monitor/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/black.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/black" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/blue.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/blue" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/brown.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/brown" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/cyan.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/cyan" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/gray.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/gray" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/green.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/green" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/light_blue.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/light_blue" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/light_gray.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/light_gray" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/lime.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/lime" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/magenta.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/magenta" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/off.json ================================================ { "parent": "refinedstorage:block/detector_nonemissive", "textures": { "torch": "refinedstorage:block/detector/cutouts/off" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/orange.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/orange" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/pink.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/pink" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/purple.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/purple" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/red.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/red" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/white.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/white" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/detector/yellow.json ================================================ { "parent": "refinedstorage:block/detector", "textures": { "torch": "refinedstorage:block/detector/cutouts/yellow" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/loader.json ================================================ { "loader": "refinedstorage:disk_manipulator", "render_type": "minecraft:cutout" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/disk_manipulator/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/disk_manipulator/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/disk_manipulator/right", "north": "refinedstorage:block/disk_manipulator/front", "particle": "refinedstorage:block/disk_manipulator/right", "south": "refinedstorage:block/disk_manipulator/back", "up": "refinedstorage:block/disk_manipulator/top", "west": "refinedstorage:block/disk_manipulator/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/fluid_grid/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/fluid_grid/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/fluid_grid/right", "north": "refinedstorage:block/fluid_grid/front", "particle": "refinedstorage:block/fluid_grid/right", "south": "refinedstorage:block/fluid_grid/back", "up": "refinedstorage:block/fluid_grid/top", "west": "refinedstorage:block/fluid_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/grid/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/grid/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/grid/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/grid/right", "north": "refinedstorage:block/grid/front", "particle": "refinedstorage:block/grid/right", "south": "refinedstorage:block/grid/back", "up": "refinedstorage:block/grid/top", "west": "refinedstorage:block/grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/black.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/black", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/blue", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/brown.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/brown", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/cyan.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/cyan", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout_nonemissive", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/disconnected", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/gray", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/green.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/green", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/light_blue", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/light_gray", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/lime.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/lime", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/magenta.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/magenta", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/orange.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/orange", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/pink.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/pink", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/purple.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/purple", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/red.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/red", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/white.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/white", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_receiver/yellow.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_receiver/network_receiver", "cutout": "refinedstorage:block/network_receiver/cutouts/yellow", "particle": "refinedstorage:block/network_receiver/network_receiver" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/black.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/black", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/blue", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/brown.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/brown", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/cyan.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/cyan", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout_nonemissive", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/disconnected", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/gray", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/green.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/green", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/light_blue", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/light_gray", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/lime.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/lime", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/magenta.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/magenta", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/orange.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/orange", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/pink.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/pink", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/purple.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/purple", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/red.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/red", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/white.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/white", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/network_transmitter/yellow.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/network_transmitter/network_transmitter", "cutout": "refinedstorage:block/network_transmitter/cutouts/yellow", "particle": "refinedstorage:block/network_transmitter/network_transmitter" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/black.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/brown.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/cyan.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout_nonemissive", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/green.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/lime.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/magenta.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/orange.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/pink.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/purple.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/red.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/white.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/pattern_grid/yellow.json ================================================ { "parent": "refinedstorage:block/cube_north_cutout", "textures": { "cutout": "refinedstorage:block/pattern_grid/cutouts/yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/pattern_grid/right", "north": "refinedstorage:block/pattern_grid/front", "particle": "refinedstorage:block/pattern_grid/right", "south": "refinedstorage:block/pattern_grid/back", "up": "refinedstorage:block/pattern_grid/top", "west": "refinedstorage:block/pattern_grid/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/black.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/black", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/blue", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/brown.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/brown", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/cyan.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/cyan", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout_nonemissive", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/disconnected", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/gray", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/green.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/green", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/light_blue", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/light_gray", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/lime.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/lime", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/magenta.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/magenta", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/orange.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/orange", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/pink.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/pink", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/purple.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/purple", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/red.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/red", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/white.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/white", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/relay/yellow.json ================================================ { "parent": "refinedstorage:block/cube_all_cutout", "textures": { "all": "refinedstorage:block/relay/relay", "cutout": "refinedstorage:block/relay/cutouts/yellow", "particle": "refinedstorage:block/relay/relay" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/black.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_black", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_black", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_black", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_black", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_black", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/blue.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_blue", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_blue", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_blue", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_blue", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/brown.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_brown", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_brown", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_brown", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_brown", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_brown", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/cyan.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_cyan", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_cyan", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_cyan", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_cyan", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_cyan", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/disconnected.json ================================================ { "parent": "refinedstorage:block/cube_cutout_nonemissive", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_disconnected", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_disconnected", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_disconnected", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_disconnected", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_disconnected", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/gray.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_gray", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_gray", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_gray", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_gray", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/green.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_green", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_green", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_green", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_green", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_green", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/light_blue.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_light_blue", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_light_blue", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_light_blue", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_light_blue", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_light_blue", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/light_gray.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_light_gray", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_light_gray", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_light_gray", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_light_gray", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_light_gray", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/lime.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_lime", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_lime", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_lime", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_lime", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_lime", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/magenta.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_magenta", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_magenta", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_magenta", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_magenta", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_magenta", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/orange.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_orange", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_orange", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_orange", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_orange", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_orange", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/pink.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_pink", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_pink", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_pink", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_pink", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_pink", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/purple.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_purple", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_purple", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_purple", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_purple", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_purple", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/red.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_red", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_red", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_red", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_red", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_red", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/white.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_white", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_white", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_white", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_white", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_white", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/security_manager/yellow.json ================================================ { "parent": "refinedstorage:block/cube_cutout", "textures": { "cutout_down": "refinedstorage:block/bottom", "cutout_east": "refinedstorage:block/security_manager/cutouts/right_yellow", "cutout_north": "refinedstorage:block/security_manager/cutouts/front_yellow", "cutout_south": "refinedstorage:block/security_manager/cutouts/back_yellow", "cutout_up": "refinedstorage:block/security_manager/cutouts/top_yellow", "cutout_west": "refinedstorage:block/security_manager/cutouts/left_yellow", "down": "refinedstorage:block/bottom", "east": "refinedstorage:block/security_manager/right", "north": "refinedstorage:block/security_manager/front", "particle": "refinedstorage:block/security_manager/front", "south": "refinedstorage:block/security_manager/back", "up": "refinedstorage:block/security_manager/top", "west": "refinedstorage:block/security_manager/left" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/black.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/black" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/blue.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/blue" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/brown.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/brown" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/cyan.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/cyan" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/disconnected.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter_nonemissive", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/disconnected" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/gray.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/gray" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/green.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/green" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/light_blue.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/light_blue" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/light_gray.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/light_gray" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/lime.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/lime" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/magenta.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/magenta" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/orange.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/orange" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/pink.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/pink" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/purple.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/purple" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/red.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/red" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/white.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/white" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/block/wireless_transmitter/yellow.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter", "textures": { "cutout": "refinedstorage:block/wireless_transmitter/cutouts/yellow" } } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/black", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/black", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_detector.json ================================================ { "parent": "refinedstorage:block/detector/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_grid.json ================================================ { "parent": "refinedstorage:block/grid/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_relay.json ================================================ { "parent": "refinedstorage:block/relay/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/black_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/black" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/blue", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/blue", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_detector.json ================================================ { "parent": "refinedstorage:block/detector/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_grid.json ================================================ { "parent": "refinedstorage:block/grid/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_relay.json ================================================ { "parent": "refinedstorage:block/relay/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/blue_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/brown", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/brown", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_detector.json ================================================ { "parent": "refinedstorage:block/detector/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_grid.json ================================================ { "parent": "refinedstorage:block/grid/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_relay.json ================================================ { "parent": "refinedstorage:block/relay/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/brown_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/brown" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/light_blue", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/crafter.json ================================================ { "parent": "refinedstorage:block/crafter/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/light_blue", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/cyan", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/cyan", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_detector.json ================================================ { "parent": "refinedstorage:block/detector/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_grid.json ================================================ { "parent": "refinedstorage:block/grid/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_relay.json ================================================ { "parent": "refinedstorage:block/relay/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/cyan_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/cyan" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/detector.json ================================================ { "parent": "refinedstorage:block/detector/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/gray", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/gray", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_detector.json ================================================ { "parent": "refinedstorage:block/detector/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_grid.json ================================================ { "parent": "refinedstorage:block/grid/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_relay.json ================================================ { "parent": "refinedstorage:block/relay/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/gray_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/green", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/green", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_detector.json ================================================ { "parent": "refinedstorage:block/detector/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_grid.json ================================================ { "parent": "refinedstorage:block/grid/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_relay.json ================================================ { "parent": "refinedstorage:block/relay/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/green_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/green" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/grid.json ================================================ { "parent": "refinedstorage:block/grid/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/light_gray", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/light_gray", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_detector.json ================================================ { "parent": "refinedstorage:block/detector/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_grid.json ================================================ { "parent": "refinedstorage:block/grid/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_relay.json ================================================ { "parent": "refinedstorage:block/relay/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/light_gray_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/light_gray" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/lime", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/lime", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_detector.json ================================================ { "parent": "refinedstorage:block/detector/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_grid.json ================================================ { "parent": "refinedstorage:block/grid/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_relay.json ================================================ { "parent": "refinedstorage:block/relay/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/lime_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/lime" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/magenta", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/magenta", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_detector.json ================================================ { "parent": "refinedstorage:block/detector/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_grid.json ================================================ { "parent": "refinedstorage:block/grid/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_relay.json ================================================ { "parent": "refinedstorage:block/relay/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/magenta_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/magenta" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/orange", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/orange", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_detector.json ================================================ { "parent": "refinedstorage:block/detector/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_grid.json ================================================ { "parent": "refinedstorage:block/grid/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_relay.json ================================================ { "parent": "refinedstorage:block/relay/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/orange_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/orange" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/pink", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/pink", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_detector.json ================================================ { "parent": "refinedstorage:block/detector/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_grid.json ================================================ { "parent": "refinedstorage:block/grid/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_relay.json ================================================ { "parent": "refinedstorage:block/relay/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/pink_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/pink" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/purple", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/purple", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_detector.json ================================================ { "parent": "refinedstorage:block/detector/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_grid.json ================================================ { "parent": "refinedstorage:block/grid/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_relay.json ================================================ { "parent": "refinedstorage:block/relay/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/purple_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/purple" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/red", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/red", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_detector.json ================================================ { "parent": "refinedstorage:block/detector/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_grid.json ================================================ { "parent": "refinedstorage:block/grid/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_relay.json ================================================ { "parent": "refinedstorage:block/relay/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/red_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/red" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/relay.json ================================================ { "parent": "refinedstorage:block/relay/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/white", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/white", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_detector.json ================================================ { "parent": "refinedstorage:block/detector/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_grid.json ================================================ { "parent": "refinedstorage:block/grid/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_relay.json ================================================ { "parent": "refinedstorage:block/relay/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/white_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/white" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/light_blue" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/yellow", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_crafter.json ================================================ { "parent": "refinedstorage:block/crafter/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_crafter_manager.json ================================================ { "parent": "refinedstorage:block/crafter_manager/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_crafting_grid.json ================================================ { "parent": "refinedstorage:block/crafting_grid/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_crafting_monitor.json ================================================ { "parent": "refinedstorage:block/crafting_monitor/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_creative_controller.json ================================================ { "overrides": [ { "model": "refinedstorage:block/controller/off", "predicate": { "refinedstorage:energy_type": 0.0 } }, { "model": "refinedstorage:block/controller/nearly_off", "predicate": { "refinedstorage:energy_type": 1.0 } }, { "model": "refinedstorage:block/controller/nearly_on", "predicate": { "refinedstorage:energy_type": 2.0 } }, { "model": "refinedstorage:block/controller/yellow", "predicate": { "refinedstorage:energy_type": 3.0 } } ] } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_detector.json ================================================ { "parent": "refinedstorage:block/detector/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_disk_manipulator.json ================================================ { "parent": "refinedstorage:block/disk_manipulator/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_fluid_grid.json ================================================ { "parent": "refinedstorage:block/fluid_grid/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_grid.json ================================================ { "parent": "refinedstorage:block/grid/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_network_receiver.json ================================================ { "parent": "refinedstorage:block/network_receiver/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_network_transmitter.json ================================================ { "parent": "refinedstorage:block/network_transmitter/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_pattern_grid.json ================================================ { "parent": "refinedstorage:block/pattern_grid/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_relay.json ================================================ { "parent": "refinedstorage:block/relay/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_security_manager.json ================================================ { "parent": "refinedstorage:block/security_manager/yellow" } ================================================ FILE: src/generated/resources/assets/refinedstorage/models/item/yellow_wireless_transmitter.json ================================================ { "parent": "refinedstorage:block/wireless_transmitter/yellow" } ================================================ FILE: src/generated/resources/data/forge/tags/blocks/relocation_not_supported.json ================================================ { "values": [ "#refinedstorage:detector", "#refinedstorage:disk_manipulator", "#refinedstorage:network_transmitter", "#refinedstorage:fluid_grid", "#refinedstorage:controller", "#refinedstorage:crafting_monitor", "#refinedstorage:pattern_grid", "#refinedstorage:wireless_transmitter", "#refinedstorage:relay", "#refinedstorage:network_receiver", "#refinedstorage:grid", "#refinedstorage:crafter", "#refinedstorage:crafter_manager", "#refinedstorage:crafting_grid", "#refinedstorage:security_manager", "#refinedstorage:creative_controller", "refinedstorage:1k_storage_block", "refinedstorage:4k_storage_block", "refinedstorage:16k_storage_block", "refinedstorage:64k_storage_block", "refinedstorage:creative_storage_block", "refinedstorage:64k_fluid_storage_block", "refinedstorage:256k_fluid_storage_block", "refinedstorage:1024k_fluid_storage_block", "refinedstorage:4096k_fluid_storage_block", "refinedstorage:creative_fluid_storage_block", "refinedstorage:importer", "refinedstorage:exporter", "refinedstorage:external_storage", "refinedstorage:disk_drive", "refinedstorage:interface", "refinedstorage:fluid_interface", "refinedstorage:storage_monitor", "refinedstorage:constructor", "refinedstorage:destructor", "refinedstorage:portable_grid", "refinedstorage:creative_portable_grid" ] } ================================================ FILE: src/generated/resources/data/packingtape/tags/block_entity_type/blacklist/problematic.json ================================================ { "values": [ "refinedstorage:controller", "refinedstorage:creative_controller", "refinedstorage:detector", "refinedstorage:disk_drive", "refinedstorage:exporter", "refinedstorage:external_storage", "refinedstorage:grid", "refinedstorage:crafting_grid", "refinedstorage:pattern_grid", "refinedstorage:fluid_grid", "refinedstorage:importer", "refinedstorage:network_transmitter", "refinedstorage:network_receiver", "refinedstorage:relay", "refinedstorage:cable", "refinedstorage:1k_storage_block", "refinedstorage:4k_storage_block", "refinedstorage:16k_storage_block", "refinedstorage:64k_storage_block", "refinedstorage:creative_storage_block", "refinedstorage:64k_fluid_storage_block", "refinedstorage:256k_fluid_storage_block", "refinedstorage:1024k_fluid_storage_block", "refinedstorage:4096k_fluid_storage_block", "refinedstorage:creative_fluid_storage_block", "refinedstorage:security_manager", "refinedstorage:interface", "refinedstorage:fluid_interface", "refinedstorage:wireless_transmitter", "refinedstorage:storage_monitor", "refinedstorage:constructor", "refinedstorage:destructor", "refinedstorage:disk_manipulator", "refinedstorage:portable_grid", "refinedstorage:creative_portable_grid", "refinedstorage:crafter", "refinedstorage:crafter_manager", "refinedstorage:crafting_monitor" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/black_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/black_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/black_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/blue_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/blue_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/blue_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/brown_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/brown_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/brown_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/cyan_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/cyan_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/cyan_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/gray_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/gray_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/gray_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/green_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/green_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/green_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/light_gray_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/light_gray_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/light_gray_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/lime_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/lime_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/lime_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/magenta_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/magenta_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/magenta_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/orange_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/orange_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/orange_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/pink_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/pink_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/pink_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/purple_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/purple_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/purple_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/red_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/red_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/red_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/white_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/white_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/white_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_controller.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_controller" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_controller" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_crafter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_crafter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafter_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_crafter_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_crafter_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_crafting_monitor.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_crafting_monitor" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_crafting_monitor" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_detector.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_detector" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_detector" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_disk_manipulator.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_disk_manipulator" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_disk_manipulator" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_receiver.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_network_receiver" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_network_receiver" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_network_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_network_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_network_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_relay.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_relay" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_relay" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_security_manager.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_security_manager" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_security_manager" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/coloring_recipes/yellow_wireless_transmitter.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:coloring_recipes/yellow_wireless_transmitter" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:controller": { "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:controller" ] ], "rewards": { "recipes": [ "refinedstorage:coloring_recipes/yellow_wireless_transmitter" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/black_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/black_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/black_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/blue_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/blue_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/blue_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/brown_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/brown_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/brown_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/cyan_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/cyan_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/cyan_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/gray_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/gray_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/gray_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/green_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/green_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/green_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/light_gray_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/light_gray_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/light_gray_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/lime_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/lime_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/lime_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/magenta_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/magenta_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/magenta_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/orange_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/orange_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/orange_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/pink_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/pink_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/pink_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/purple_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/purple_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/purple_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/red_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/red_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/red_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/white_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/white_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/white_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/crafting_grid/yellow_crafting_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:crafting_grid/yellow_crafting_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:crafting_grid/yellow_crafting_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/black_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/black_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/black_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/blue_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/blue_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/blue_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/brown_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/brown_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/brown_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/cyan_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/cyan_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/cyan_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/gray_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/gray_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/gray_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/green_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/green_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/green_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/light_gray_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/light_gray_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/light_gray_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/lime_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/lime_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/lime_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/magenta_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/magenta_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/magenta_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/orange_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/orange_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/orange_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/pink_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/pink_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/pink_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/purple_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/purple_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/purple_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/red_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/red_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/red_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/white_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/white_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/white_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/fluid_grid/yellow_fluid_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:fluid_grid/yellow_fluid_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:fluid_grid/yellow_fluid_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/black_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/black_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/black_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/blue_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/blue_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/blue_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/brown_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/brown_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/brown_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/cyan_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/cyan_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/cyan_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/gray_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/gray_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/gray_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/green_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/green_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/green_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/light_gray_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/light_gray_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/light_gray_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/lime_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/lime_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/lime_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/magenta_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/magenta_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/magenta_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/orange_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/orange_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/orange_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/pink_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/pink_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/pink_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/purple_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/purple_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/purple_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/red_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/red_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/red_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/white_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/white_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/white_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/advancements/recipes/misc/pattern_grid/yellow_pattern_grid.json ================================================ { "parent": "minecraft:recipes/root", "criteria": { "has_the_recipe": { "conditions": { "recipe": "refinedstorage:pattern_grid/yellow_pattern_grid" }, "trigger": "minecraft:recipe_unlocked" }, "refinedstorage:grid": { "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] }, "trigger": "minecraft:inventory_changed" } }, "requirements": [ [ "has_the_recipe", "refinedstorage:grid" ] ], "rewards": { "recipes": [ "refinedstorage:pattern_grid/yellow_pattern_grid" ] } } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:black_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:black_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/black_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:black_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/black_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:blue_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:blue_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/blue_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:blue_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/blue_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:brown_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:brown_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/brown_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:brown_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/brown_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:cyan_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:cyan_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/cyan_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cyan_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/cyan_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:gray_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:gray_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/gray_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:gray_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/gray_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:green_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:green_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/green_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:green_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/green_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:light_gray_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:light_gray_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/light_gray_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:light_gray_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/light_gray_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:lime_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:lime_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/lime_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:lime_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/lime_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:magenta_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:magenta_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/magenta_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:magenta_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/magenta_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:orange_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:orange_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/orange_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:orange_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/orange_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:pink_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:pink_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/pink_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:pink_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/pink_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:purple_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:purple_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/purple_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:purple_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/purple_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:red_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:red_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/red_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:red_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/red_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:white_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:white_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/white_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:white_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/white_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:controller" } ], "name": "refinedstorage:yellow_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "functions": [ { "function": "refinedstorage:crafter" } ], "name": "refinedstorage:yellow_crafter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_crafter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafter_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_crafter_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_crafter_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafting_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_crafting_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_crafting_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_crafting_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_crafting_monitor" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_crafting_monitor" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_creative_controller.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_creative_controller" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_creative_controller" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_detector.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_detector" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_detector" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_disk_manipulator.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_disk_manipulator" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_disk_manipulator" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_fluid_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_fluid_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_fluid_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_network_receiver.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_network_receiver" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_network_receiver" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_network_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_network_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_network_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_pattern_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_pattern_grid" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_pattern_grid" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_relay.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_relay" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_relay" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_security_manager.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_security_manager" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_security_manager" } ================================================ FILE: src/generated/resources/data/refinedstorage/loot_tables/blocks/yellow_wireless_transmitter.json ================================================ { "type": "minecraft:block", "pools": [ { "bonus_rolls": 0.0, "conditions": [ { "condition": "minecraft:survives_explosion" } ], "entries": [ { "type": "minecraft:item", "name": "refinedstorage:yellow_wireless_transmitter" } ], "rolls": 1.0 } ], "random_sequence": "refinedstorage:blocks/yellow_wireless_transmitter" } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/black_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/black" } ], "result": { "item": "refinedstorage:black_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/blue_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/blue" } ], "result": { "item": "refinedstorage:blue_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/brown_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/brown" } ], "result": { "item": "refinedstorage:brown_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/cyan_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/cyan" } ], "result": { "item": "refinedstorage:cyan_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/gray_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/gray" } ], "result": { "item": "refinedstorage:gray_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/green_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/green" } ], "result": { "item": "refinedstorage:green_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/light_gray_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/light_gray" } ], "result": { "item": "refinedstorage:light_gray_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/lime_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/lime" } ], "result": { "item": "refinedstorage:lime_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/magenta_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/magenta" } ], "result": { "item": "refinedstorage:magenta_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/orange_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/orange" } ], "result": { "item": "refinedstorage:orange_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/pink_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/pink" } ], "result": { "item": "refinedstorage:pink_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/purple_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/purple" } ], "result": { "item": "refinedstorage:purple_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/red_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/red" } ], "result": { "item": "refinedstorage:red_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/white_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/white" } ], "result": { "item": "refinedstorage:white_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/light_blue" } ], "result": { "item": "refinedstorage:wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_controller.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:controller" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_controller" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_crafter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafter_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafter_manager" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_crafter_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_grid" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:crafting_monitor" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_crafting_monitor" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_detector.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:detector" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_detector" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_disk_manipulator.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:disk_manipulator" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_disk_manipulator" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:fluid_grid" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:grid" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_network_receiver.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_receiver" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_network_receiver" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_network_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:network_transmitter" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_network_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:pattern_grid" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_relay.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:relay" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_relay" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_security_manager.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:security_manager" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_security_manager" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/coloring_recipes/yellow_wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "group": "refinedstorage", "ingredients": [ { "tag": "refinedstorage:wireless_transmitter" }, { "tag": "forge:dyes/yellow" } ], "result": { "item": "refinedstorage:yellow_wireless_transmitter" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/black_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:black_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:black_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/blue_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:blue_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:blue_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/brown_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:brown_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:brown_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/cyan_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:cyan_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:cyan_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/gray_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:gray_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/green_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:green_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:green_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/light_gray_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:light_gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:light_gray_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/lime_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:lime_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:lime_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/magenta_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:magenta_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:magenta_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/orange_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:orange_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:orange_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/pink_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:pink_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:pink_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/purple_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:purple_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:purple_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/red_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:red_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:red_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/white_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:white_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:white_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/crafting_grid/yellow_crafting_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:yellow_grid" }, { "item": "refinedstorage:advanced_processor" }, { "tag": "refinedstorage:crafting_tables" } ], "result": { "item": "refinedstorage:yellow_crafting_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/black_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:black_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:black_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/blue_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:blue_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:blue_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/brown_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:brown_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:brown_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/cyan_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:cyan_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:cyan_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/gray_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:gray_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/green_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:green_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:green_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/light_gray_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:light_gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:light_gray_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/lime_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:lime_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:lime_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/magenta_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:magenta_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:magenta_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/orange_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:orange_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:orange_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/pink_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:pink_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:pink_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/purple_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:purple_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:purple_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/red_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:red_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:red_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/white_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:white_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:white_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/fluid_grid/yellow_fluid_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:yellow_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:yellow_fluid_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/black_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:black_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:black_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/blue_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:blue_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:blue_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/brown_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:brown_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:brown_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/cyan_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:cyan_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:cyan_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/gray_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:gray_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/green_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:green_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:green_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/light_gray_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:light_gray_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:light_gray_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/lime_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:lime_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:lime_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/magenta_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:magenta_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:magenta_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/orange_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:orange_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:orange_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/pink_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:pink_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:pink_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/purple_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:purple_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:purple_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/red_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:red_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:red_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/white_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:white_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:white_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/recipes/pattern_grid/yellow_pattern_grid.json ================================================ { "type": "minecraft:crafting_shapeless", "category": "misc", "ingredients": [ { "item": "refinedstorage:yellow_grid" }, { "item": "refinedstorage:advanced_processor" }, { "item": "refinedstorage:pattern" } ], "result": { "item": "refinedstorage:yellow_pattern_grid" } } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/controller.json ================================================ { "values": [ "refinedstorage:white_controller", "refinedstorage:orange_controller", "refinedstorage:magenta_controller", "refinedstorage:controller", "refinedstorage:yellow_controller", "refinedstorage:lime_controller", "refinedstorage:pink_controller", "refinedstorage:gray_controller", "refinedstorage:light_gray_controller", "refinedstorage:cyan_controller", "refinedstorage:purple_controller", "refinedstorage:blue_controller", "refinedstorage:brown_controller", "refinedstorage:green_controller", "refinedstorage:red_controller", "refinedstorage:black_controller" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/crafter.json ================================================ { "values": [ "refinedstorage:white_crafter", "refinedstorage:orange_crafter", "refinedstorage:magenta_crafter", "refinedstorage:crafter", "refinedstorage:yellow_crafter", "refinedstorage:lime_crafter", "refinedstorage:pink_crafter", "refinedstorage:gray_crafter", "refinedstorage:light_gray_crafter", "refinedstorage:cyan_crafter", "refinedstorage:purple_crafter", "refinedstorage:blue_crafter", "refinedstorage:brown_crafter", "refinedstorage:green_crafter", "refinedstorage:red_crafter", "refinedstorage:black_crafter" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/crafter_manager.json ================================================ { "values": [ "refinedstorage:white_crafter_manager", "refinedstorage:orange_crafter_manager", "refinedstorage:magenta_crafter_manager", "refinedstorage:crafter_manager", "refinedstorage:yellow_crafter_manager", "refinedstorage:lime_crafter_manager", "refinedstorage:pink_crafter_manager", "refinedstorage:gray_crafter_manager", "refinedstorage:light_gray_crafter_manager", "refinedstorage:cyan_crafter_manager", "refinedstorage:purple_crafter_manager", "refinedstorage:blue_crafter_manager", "refinedstorage:brown_crafter_manager", "refinedstorage:green_crafter_manager", "refinedstorage:red_crafter_manager", "refinedstorage:black_crafter_manager" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/crafting_grid.json ================================================ { "values": [ "refinedstorage:white_crafting_grid", "refinedstorage:orange_crafting_grid", "refinedstorage:magenta_crafting_grid", "refinedstorage:crafting_grid", "refinedstorage:yellow_crafting_grid", "refinedstorage:lime_crafting_grid", "refinedstorage:pink_crafting_grid", "refinedstorage:gray_crafting_grid", "refinedstorage:light_gray_crafting_grid", "refinedstorage:cyan_crafting_grid", "refinedstorage:purple_crafting_grid", "refinedstorage:blue_crafting_grid", "refinedstorage:brown_crafting_grid", "refinedstorage:green_crafting_grid", "refinedstorage:red_crafting_grid", "refinedstorage:black_crafting_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/crafting_monitor.json ================================================ { "values": [ "refinedstorage:white_crafting_monitor", "refinedstorage:orange_crafting_monitor", "refinedstorage:magenta_crafting_monitor", "refinedstorage:crafting_monitor", "refinedstorage:yellow_crafting_monitor", "refinedstorage:lime_crafting_monitor", "refinedstorage:pink_crafting_monitor", "refinedstorage:gray_crafting_monitor", "refinedstorage:light_gray_crafting_monitor", "refinedstorage:cyan_crafting_monitor", "refinedstorage:purple_crafting_monitor", "refinedstorage:blue_crafting_monitor", "refinedstorage:brown_crafting_monitor", "refinedstorage:green_crafting_monitor", "refinedstorage:red_crafting_monitor", "refinedstorage:black_crafting_monitor" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/creative_controller.json ================================================ { "values": [ "refinedstorage:white_creative_controller", "refinedstorage:orange_creative_controller", "refinedstorage:magenta_creative_controller", "refinedstorage:creative_controller", "refinedstorage:yellow_creative_controller", "refinedstorage:lime_creative_controller", "refinedstorage:pink_creative_controller", "refinedstorage:gray_creative_controller", "refinedstorage:light_gray_creative_controller", "refinedstorage:cyan_creative_controller", "refinedstorage:purple_creative_controller", "refinedstorage:blue_creative_controller", "refinedstorage:brown_creative_controller", "refinedstorage:green_creative_controller", "refinedstorage:red_creative_controller", "refinedstorage:black_creative_controller" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/detector.json ================================================ { "values": [ "refinedstorage:white_detector", "refinedstorage:orange_detector", "refinedstorage:magenta_detector", "refinedstorage:detector", "refinedstorage:yellow_detector", "refinedstorage:lime_detector", "refinedstorage:pink_detector", "refinedstorage:gray_detector", "refinedstorage:light_gray_detector", "refinedstorage:cyan_detector", "refinedstorage:purple_detector", "refinedstorage:blue_detector", "refinedstorage:brown_detector", "refinedstorage:green_detector", "refinedstorage:red_detector", "refinedstorage:black_detector" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/disk_manipulator.json ================================================ { "values": [ "refinedstorage:white_disk_manipulator", "refinedstorage:orange_disk_manipulator", "refinedstorage:magenta_disk_manipulator", "refinedstorage:disk_manipulator", "refinedstorage:yellow_disk_manipulator", "refinedstorage:lime_disk_manipulator", "refinedstorage:pink_disk_manipulator", "refinedstorage:gray_disk_manipulator", "refinedstorage:light_gray_disk_manipulator", "refinedstorage:cyan_disk_manipulator", "refinedstorage:purple_disk_manipulator", "refinedstorage:blue_disk_manipulator", "refinedstorage:brown_disk_manipulator", "refinedstorage:green_disk_manipulator", "refinedstorage:red_disk_manipulator", "refinedstorage:black_disk_manipulator" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/fluid_grid.json ================================================ { "values": [ "refinedstorage:white_fluid_grid", "refinedstorage:orange_fluid_grid", "refinedstorage:magenta_fluid_grid", "refinedstorage:fluid_grid", "refinedstorage:yellow_fluid_grid", "refinedstorage:lime_fluid_grid", "refinedstorage:pink_fluid_grid", "refinedstorage:gray_fluid_grid", "refinedstorage:light_gray_fluid_grid", "refinedstorage:cyan_fluid_grid", "refinedstorage:purple_fluid_grid", "refinedstorage:blue_fluid_grid", "refinedstorage:brown_fluid_grid", "refinedstorage:green_fluid_grid", "refinedstorage:red_fluid_grid", "refinedstorage:black_fluid_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/grid.json ================================================ { "values": [ "refinedstorage:white_grid", "refinedstorage:orange_grid", "refinedstorage:magenta_grid", "refinedstorage:grid", "refinedstorage:yellow_grid", "refinedstorage:lime_grid", "refinedstorage:pink_grid", "refinedstorage:gray_grid", "refinedstorage:light_gray_grid", "refinedstorage:cyan_grid", "refinedstorage:purple_grid", "refinedstorage:blue_grid", "refinedstorage:brown_grid", "refinedstorage:green_grid", "refinedstorage:red_grid", "refinedstorage:black_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/network_receiver.json ================================================ { "values": [ "refinedstorage:white_network_receiver", "refinedstorage:orange_network_receiver", "refinedstorage:magenta_network_receiver", "refinedstorage:network_receiver", "refinedstorage:yellow_network_receiver", "refinedstorage:lime_network_receiver", "refinedstorage:pink_network_receiver", "refinedstorage:gray_network_receiver", "refinedstorage:light_gray_network_receiver", "refinedstorage:cyan_network_receiver", "refinedstorage:purple_network_receiver", "refinedstorage:blue_network_receiver", "refinedstorage:brown_network_receiver", "refinedstorage:green_network_receiver", "refinedstorage:red_network_receiver", "refinedstorage:black_network_receiver" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/network_transmitter.json ================================================ { "values": [ "refinedstorage:white_network_transmitter", "refinedstorage:orange_network_transmitter", "refinedstorage:magenta_network_transmitter", "refinedstorage:network_transmitter", "refinedstorage:yellow_network_transmitter", "refinedstorage:lime_network_transmitter", "refinedstorage:pink_network_transmitter", "refinedstorage:gray_network_transmitter", "refinedstorage:light_gray_network_transmitter", "refinedstorage:cyan_network_transmitter", "refinedstorage:purple_network_transmitter", "refinedstorage:blue_network_transmitter", "refinedstorage:brown_network_transmitter", "refinedstorage:green_network_transmitter", "refinedstorage:red_network_transmitter", "refinedstorage:black_network_transmitter" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/pattern_grid.json ================================================ { "values": [ "refinedstorage:white_pattern_grid", "refinedstorage:orange_pattern_grid", "refinedstorage:magenta_pattern_grid", "refinedstorage:pattern_grid", "refinedstorage:yellow_pattern_grid", "refinedstorage:lime_pattern_grid", "refinedstorage:pink_pattern_grid", "refinedstorage:gray_pattern_grid", "refinedstorage:light_gray_pattern_grid", "refinedstorage:cyan_pattern_grid", "refinedstorage:purple_pattern_grid", "refinedstorage:blue_pattern_grid", "refinedstorage:brown_pattern_grid", "refinedstorage:green_pattern_grid", "refinedstorage:red_pattern_grid", "refinedstorage:black_pattern_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/relay.json ================================================ { "values": [ "refinedstorage:white_relay", "refinedstorage:orange_relay", "refinedstorage:magenta_relay", "refinedstorage:relay", "refinedstorage:yellow_relay", "refinedstorage:lime_relay", "refinedstorage:pink_relay", "refinedstorage:gray_relay", "refinedstorage:light_gray_relay", "refinedstorage:cyan_relay", "refinedstorage:purple_relay", "refinedstorage:blue_relay", "refinedstorage:brown_relay", "refinedstorage:green_relay", "refinedstorage:red_relay", "refinedstorage:black_relay" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/security_manager.json ================================================ { "values": [ "refinedstorage:white_security_manager", "refinedstorage:orange_security_manager", "refinedstorage:magenta_security_manager", "refinedstorage:security_manager", "refinedstorage:yellow_security_manager", "refinedstorage:lime_security_manager", "refinedstorage:pink_security_manager", "refinedstorage:gray_security_manager", "refinedstorage:light_gray_security_manager", "refinedstorage:cyan_security_manager", "refinedstorage:purple_security_manager", "refinedstorage:blue_security_manager", "refinedstorage:brown_security_manager", "refinedstorage:green_security_manager", "refinedstorage:red_security_manager", "refinedstorage:black_security_manager" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/blocks/wireless_transmitter.json ================================================ { "values": [ "refinedstorage:white_wireless_transmitter", "refinedstorage:orange_wireless_transmitter", "refinedstorage:magenta_wireless_transmitter", "refinedstorage:wireless_transmitter", "refinedstorage:yellow_wireless_transmitter", "refinedstorage:lime_wireless_transmitter", "refinedstorage:pink_wireless_transmitter", "refinedstorage:gray_wireless_transmitter", "refinedstorage:light_gray_wireless_transmitter", "refinedstorage:cyan_wireless_transmitter", "refinedstorage:purple_wireless_transmitter", "refinedstorage:blue_wireless_transmitter", "refinedstorage:brown_wireless_transmitter", "refinedstorage:green_wireless_transmitter", "refinedstorage:red_wireless_transmitter", "refinedstorage:black_wireless_transmitter" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/controller.json ================================================ { "values": [ "refinedstorage:white_controller", "refinedstorage:orange_controller", "refinedstorage:magenta_controller", "refinedstorage:controller", "refinedstorage:yellow_controller", "refinedstorage:lime_controller", "refinedstorage:pink_controller", "refinedstorage:gray_controller", "refinedstorage:light_gray_controller", "refinedstorage:cyan_controller", "refinedstorage:purple_controller", "refinedstorage:blue_controller", "refinedstorage:brown_controller", "refinedstorage:green_controller", "refinedstorage:red_controller", "refinedstorage:black_controller" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/crafter.json ================================================ { "values": [ "refinedstorage:white_crafter", "refinedstorage:orange_crafter", "refinedstorage:magenta_crafter", "refinedstorage:crafter", "refinedstorage:yellow_crafter", "refinedstorage:lime_crafter", "refinedstorage:pink_crafter", "refinedstorage:gray_crafter", "refinedstorage:light_gray_crafter", "refinedstorage:cyan_crafter", "refinedstorage:purple_crafter", "refinedstorage:blue_crafter", "refinedstorage:brown_crafter", "refinedstorage:green_crafter", "refinedstorage:red_crafter", "refinedstorage:black_crafter" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/crafter_manager.json ================================================ { "values": [ "refinedstorage:white_crafter_manager", "refinedstorage:orange_crafter_manager", "refinedstorage:magenta_crafter_manager", "refinedstorage:crafter_manager", "refinedstorage:yellow_crafter_manager", "refinedstorage:lime_crafter_manager", "refinedstorage:pink_crafter_manager", "refinedstorage:gray_crafter_manager", "refinedstorage:light_gray_crafter_manager", "refinedstorage:cyan_crafter_manager", "refinedstorage:purple_crafter_manager", "refinedstorage:blue_crafter_manager", "refinedstorage:brown_crafter_manager", "refinedstorage:green_crafter_manager", "refinedstorage:red_crafter_manager", "refinedstorage:black_crafter_manager" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/crafting_grid.json ================================================ { "values": [ "refinedstorage:white_crafting_grid", "refinedstorage:orange_crafting_grid", "refinedstorage:magenta_crafting_grid", "refinedstorage:crafting_grid", "refinedstorage:yellow_crafting_grid", "refinedstorage:lime_crafting_grid", "refinedstorage:pink_crafting_grid", "refinedstorage:gray_crafting_grid", "refinedstorage:light_gray_crafting_grid", "refinedstorage:cyan_crafting_grid", "refinedstorage:purple_crafting_grid", "refinedstorage:blue_crafting_grid", "refinedstorage:brown_crafting_grid", "refinedstorage:green_crafting_grid", "refinedstorage:red_crafting_grid", "refinedstorage:black_crafting_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/crafting_monitor.json ================================================ { "values": [ "refinedstorage:white_crafting_monitor", "refinedstorage:orange_crafting_monitor", "refinedstorage:magenta_crafting_monitor", "refinedstorage:crafting_monitor", "refinedstorage:yellow_crafting_monitor", "refinedstorage:lime_crafting_monitor", "refinedstorage:pink_crafting_monitor", "refinedstorage:gray_crafting_monitor", "refinedstorage:light_gray_crafting_monitor", "refinedstorage:cyan_crafting_monitor", "refinedstorage:purple_crafting_monitor", "refinedstorage:blue_crafting_monitor", "refinedstorage:brown_crafting_monitor", "refinedstorage:green_crafting_monitor", "refinedstorage:red_crafting_monitor", "refinedstorage:black_crafting_monitor" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/detector.json ================================================ { "values": [ "refinedstorage:white_detector", "refinedstorage:orange_detector", "refinedstorage:magenta_detector", "refinedstorage:detector", "refinedstorage:yellow_detector", "refinedstorage:lime_detector", "refinedstorage:pink_detector", "refinedstorage:gray_detector", "refinedstorage:light_gray_detector", "refinedstorage:cyan_detector", "refinedstorage:purple_detector", "refinedstorage:blue_detector", "refinedstorage:brown_detector", "refinedstorage:green_detector", "refinedstorage:red_detector", "refinedstorage:black_detector" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/disk_manipulator.json ================================================ { "values": [ "refinedstorage:white_disk_manipulator", "refinedstorage:orange_disk_manipulator", "refinedstorage:magenta_disk_manipulator", "refinedstorage:disk_manipulator", "refinedstorage:yellow_disk_manipulator", "refinedstorage:lime_disk_manipulator", "refinedstorage:pink_disk_manipulator", "refinedstorage:gray_disk_manipulator", "refinedstorage:light_gray_disk_manipulator", "refinedstorage:cyan_disk_manipulator", "refinedstorage:purple_disk_manipulator", "refinedstorage:blue_disk_manipulator", "refinedstorage:brown_disk_manipulator", "refinedstorage:green_disk_manipulator", "refinedstorage:red_disk_manipulator", "refinedstorage:black_disk_manipulator" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/fluid_grid.json ================================================ { "values": [ "refinedstorage:white_fluid_grid", "refinedstorage:orange_fluid_grid", "refinedstorage:magenta_fluid_grid", "refinedstorage:fluid_grid", "refinedstorage:yellow_fluid_grid", "refinedstorage:lime_fluid_grid", "refinedstorage:pink_fluid_grid", "refinedstorage:gray_fluid_grid", "refinedstorage:light_gray_fluid_grid", "refinedstorage:cyan_fluid_grid", "refinedstorage:purple_fluid_grid", "refinedstorage:blue_fluid_grid", "refinedstorage:brown_fluid_grid", "refinedstorage:green_fluid_grid", "refinedstorage:red_fluid_grid", "refinedstorage:black_fluid_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/grid.json ================================================ { "values": [ "refinedstorage:white_grid", "refinedstorage:orange_grid", "refinedstorage:magenta_grid", "refinedstorage:grid", "refinedstorage:yellow_grid", "refinedstorage:lime_grid", "refinedstorage:pink_grid", "refinedstorage:gray_grid", "refinedstorage:light_gray_grid", "refinedstorage:cyan_grid", "refinedstorage:purple_grid", "refinedstorage:blue_grid", "refinedstorage:brown_grid", "refinedstorage:green_grid", "refinedstorage:red_grid", "refinedstorage:black_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/network_receiver.json ================================================ { "values": [ "refinedstorage:white_network_receiver", "refinedstorage:orange_network_receiver", "refinedstorage:magenta_network_receiver", "refinedstorage:network_receiver", "refinedstorage:yellow_network_receiver", "refinedstorage:lime_network_receiver", "refinedstorage:pink_network_receiver", "refinedstorage:gray_network_receiver", "refinedstorage:light_gray_network_receiver", "refinedstorage:cyan_network_receiver", "refinedstorage:purple_network_receiver", "refinedstorage:blue_network_receiver", "refinedstorage:brown_network_receiver", "refinedstorage:green_network_receiver", "refinedstorage:red_network_receiver", "refinedstorage:black_network_receiver" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/network_transmitter.json ================================================ { "values": [ "refinedstorage:white_network_transmitter", "refinedstorage:orange_network_transmitter", "refinedstorage:magenta_network_transmitter", "refinedstorage:network_transmitter", "refinedstorage:yellow_network_transmitter", "refinedstorage:lime_network_transmitter", "refinedstorage:pink_network_transmitter", "refinedstorage:gray_network_transmitter", "refinedstorage:light_gray_network_transmitter", "refinedstorage:cyan_network_transmitter", "refinedstorage:purple_network_transmitter", "refinedstorage:blue_network_transmitter", "refinedstorage:brown_network_transmitter", "refinedstorage:green_network_transmitter", "refinedstorage:red_network_transmitter", "refinedstorage:black_network_transmitter" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/pattern_grid.json ================================================ { "values": [ "refinedstorage:white_pattern_grid", "refinedstorage:orange_pattern_grid", "refinedstorage:magenta_pattern_grid", "refinedstorage:pattern_grid", "refinedstorage:yellow_pattern_grid", "refinedstorage:lime_pattern_grid", "refinedstorage:pink_pattern_grid", "refinedstorage:gray_pattern_grid", "refinedstorage:light_gray_pattern_grid", "refinedstorage:cyan_pattern_grid", "refinedstorage:purple_pattern_grid", "refinedstorage:blue_pattern_grid", "refinedstorage:brown_pattern_grid", "refinedstorage:green_pattern_grid", "refinedstorage:red_pattern_grid", "refinedstorage:black_pattern_grid" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/relay.json ================================================ { "values": [ "refinedstorage:white_relay", "refinedstorage:orange_relay", "refinedstorage:magenta_relay", "refinedstorage:relay", "refinedstorage:yellow_relay", "refinedstorage:lime_relay", "refinedstorage:pink_relay", "refinedstorage:gray_relay", "refinedstorage:light_gray_relay", "refinedstorage:cyan_relay", "refinedstorage:purple_relay", "refinedstorage:blue_relay", "refinedstorage:brown_relay", "refinedstorage:green_relay", "refinedstorage:red_relay", "refinedstorage:black_relay" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/security_manager.json ================================================ { "values": [ "refinedstorage:white_security_manager", "refinedstorage:orange_security_manager", "refinedstorage:magenta_security_manager", "refinedstorage:security_manager", "refinedstorage:yellow_security_manager", "refinedstorage:lime_security_manager", "refinedstorage:pink_security_manager", "refinedstorage:gray_security_manager", "refinedstorage:light_gray_security_manager", "refinedstorage:cyan_security_manager", "refinedstorage:purple_security_manager", "refinedstorage:blue_security_manager", "refinedstorage:brown_security_manager", "refinedstorage:green_security_manager", "refinedstorage:red_security_manager", "refinedstorage:black_security_manager" ] } ================================================ FILE: src/generated/resources/data/refinedstorage/tags/items/wireless_transmitter.json ================================================ { "values": [ "refinedstorage:white_wireless_transmitter", "refinedstorage:orange_wireless_transmitter", "refinedstorage:magenta_wireless_transmitter", "refinedstorage:wireless_transmitter", "refinedstorage:yellow_wireless_transmitter", "refinedstorage:lime_wireless_transmitter", "refinedstorage:pink_wireless_transmitter", "refinedstorage:gray_wireless_transmitter", "refinedstorage:light_gray_wireless_transmitter", "refinedstorage:cyan_wireless_transmitter", "refinedstorage:purple_wireless_transmitter", "refinedstorage:blue_wireless_transmitter", "refinedstorage:brown_wireless_transmitter", "refinedstorage:green_wireless_transmitter", "refinedstorage:red_wireless_transmitter", "refinedstorage:black_wireless_transmitter" ] } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RS.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.config.ClientConfig; import com.refinedmods.refinedstorage.config.ServerConfig; import com.refinedmods.refinedstorage.datageneration.DataGenerators; import com.refinedmods.refinedstorage.integration.curios.CuriosIntegration; import com.refinedmods.refinedstorage.network.NetworkHandler; import com.refinedmods.refinedstorage.setup.ClientSetup; import com.refinedmods.refinedstorage.setup.CommonSetup; import com.refinedmods.refinedstorage.setup.ServerSetup; import net.neoforged.api.distmarker.Dist; import net.neoforged.bus.api.IEventBus; import net.neoforged.fml.ModLoadingContext; import net.neoforged.fml.common.Mod; import net.neoforged.fml.config.ModConfig; import net.neoforged.fml.loading.FMLEnvironment; import net.neoforged.neoforge.common.NeoForge; @Mod(RS.ID) public final class RS { public static final String ID = "refinedstorage"; public static final String NAME = "Refined Storage"; public static final NetworkHandler NETWORK_HANDLER = new NetworkHandler(); public static final ServerConfig SERVER_CONFIG = new ServerConfig(); public static final ClientConfig CLIENT_CONFIG = new ClientConfig(); public RS(IEventBus eventBus) { if (FMLEnvironment.dist == Dist.CLIENT) { eventBus.addListener(ClientSetup::onClientSetup); eventBus.addListener(ClientSetup::registerMenuScreens); eventBus.addListener(ClientSetup::onModelBake); eventBus.addListener(ClientSetup::onRegisterAdditionalModels); eventBus.addListener(ClientSetup::onRegisterModelGeometry); eventBus.addListener(ClientSetup::onRegisterKeymappings); eventBus.addListener(ClientSetup::onRegisterColorBindings); NeoForge.EVENT_BUS.addListener(ClientSetup::addReloadListener); } NeoForge.EVENT_BUS.register(new ServerSetup()); ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, SERVER_CONFIG.getSpec()); ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, CLIENT_CONFIG.getSpec()); RSBlocks.register(eventBus); RSItems.register(eventBus); eventBus.addListener(CommonSetup::onCommonSetup); eventBus.addListener(CommonSetup::onRegister); eventBus.addListener(CommonSetup::onRegisterCapabilities); eventBus.addListener(CommonSetup::onRegisterNetworkPackets); eventBus.register(new DataGenerators()); eventBus.register(new CuriosIntegration()); RSContainerMenus.REGISTRY.register(eventBus); RSBlockEntities.REGISTRY.register(eventBus); RSRecipeSerializers.REGISTRY.register(eventBus); API.deliver(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSBlockEntities.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.blockentity.*; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.neoforged.neoforge.registries.DeferredRegister; import net.neoforged.neoforge.registries.DeferredHolder; public final class RSBlockEntities { public static final DeferredRegister> REGISTRY = DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, RS.ID); public static final DeferredHolder, BlockEntityType> CONTROLLER = REGISTRY.register("controller", () -> registerSynchronizationParameters(ControllerBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new ControllerBlockEntity(NetworkType.NORMAL, pos, state), RSBlocks.CONTROLLER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> CREATIVE_CONTROLLER = REGISTRY.register("creative_controller", () -> registerSynchronizationParameters(ControllerBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new ControllerBlockEntity(NetworkType.CREATIVE, pos, state), RSBlocks.CREATIVE_CONTROLLER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> DETECTOR = REGISTRY.register("detector", () -> registerSynchronizationParameters(DetectorBlockEntity.SPEC, BlockEntityType.Builder.of(DetectorBlockEntity::new, RSBlocks.DETECTOR.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> DISK_DRIVE = REGISTRY.register("disk_drive", () -> registerSynchronizationParameters(DiskDriveBlockEntity.SPEC, BlockEntityType.Builder.of(DiskDriveBlockEntity::new, RSBlocks.DISK_DRIVE.get()).build(null))); public static final DeferredHolder, BlockEntityType> EXPORTER = REGISTRY.register("exporter", () -> registerSynchronizationParameters(ExporterBlockEntity.SPEC, BlockEntityType.Builder.of(ExporterBlockEntity::new, RSBlocks.EXPORTER.get()).build(null))); public static final DeferredHolder, BlockEntityType> EXTERNAL_STORAGE = REGISTRY.register("external_storage", () -> registerSynchronizationParameters(ExternalStorageBlockEntity.SPEC, BlockEntityType.Builder.of(ExternalStorageBlockEntity::new, RSBlocks.EXTERNAL_STORAGE.get()).build(null))); public static final DeferredHolder, BlockEntityType> GRID = REGISTRY.register("grid", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.NORMAL, pos, state), RSBlocks.GRID.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> CRAFTING_GRID = REGISTRY.register("crafting_grid", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.CRAFTING, pos, state), RSBlocks.CRAFTING_GRID.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> PATTERN_GRID = REGISTRY.register("pattern_grid", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.PATTERN, pos, state), RSBlocks.PATTERN_GRID.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> FLUID_GRID = REGISTRY.register("fluid_grid", () -> registerSynchronizationParameters(GridBlockEntity.SPEC, BlockEntityType.Builder.of((pos, state) -> new GridBlockEntity(GridType.FLUID, pos, state), RSBlocks.FLUID_GRID.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> IMPORTER = REGISTRY.register("importer", () -> registerSynchronizationParameters(ImporterBlockEntity.SPEC, BlockEntityType.Builder.of(ImporterBlockEntity::new, RSBlocks.IMPORTER.get()).build(null))); public static final DeferredHolder, BlockEntityType> NETWORK_TRANSMITTER = REGISTRY.register("network_transmitter", () -> registerSynchronizationParameters(NetworkTransmitterBlockEntity.SPEC, BlockEntityType.Builder.of(NetworkTransmitterBlockEntity::new, RSBlocks.NETWORK_TRANSMITTER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> NETWORK_RECEIVER = REGISTRY.register("network_receiver", () -> registerSynchronizationParameters(NetworkReceiverBlockEntity.SPEC, BlockEntityType.Builder.of(NetworkReceiverBlockEntity::new, RSBlocks.NETWORK_RECEIVER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> RELAY = REGISTRY.register("relay", () -> registerSynchronizationParameters(RelayBlockEntity.SPEC, BlockEntityType.Builder.of(RelayBlockEntity::new, RSBlocks.RELAY.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> CABLE = REGISTRY.register("cable", () -> registerSynchronizationParameters(CableBlockEntity.SPEC, BlockEntityType.Builder.of(CableBlockEntity::new, RSBlocks.CABLE.get()).build(null))); public static final DeferredHolder, BlockEntityType> ONE_K_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> FOUR_K_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> SIXTEEN_K_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> SIXTY_FOUR_K_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> CREATIVE_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> SIXTY_FOUR_K_FLUID_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> CREATIVE_FLUID_STORAGE_BLOCK = 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))); public static final DeferredHolder, BlockEntityType> SECURITY_MANAGER = REGISTRY.register("security_manager", () -> registerSynchronizationParameters(SecurityManagerBlockEntity.SPEC, BlockEntityType.Builder.of(SecurityManagerBlockEntity::new, RSBlocks.SECURITY_MANAGER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> INTERFACE = REGISTRY.register("interface", () -> registerSynchronizationParameters(InterfaceBlockEntity.SPEC, BlockEntityType.Builder.of(InterfaceBlockEntity::new, RSBlocks.INTERFACE.get()).build(null))); public static final DeferredHolder, BlockEntityType> FLUID_INTERFACE = REGISTRY.register("fluid_interface", () -> registerSynchronizationParameters(FluidInterfaceBlockEntity.SPEC, BlockEntityType.Builder.of(FluidInterfaceBlockEntity::new, RSBlocks.FLUID_INTERFACE.get()).build(null))); public static final DeferredHolder, BlockEntityType> WIRELESS_TRANSMITTER = REGISTRY.register("wireless_transmitter", () -> registerSynchronizationParameters(WirelessTransmitterBlockEntity.SPEC, BlockEntityType.Builder.of(WirelessTransmitterBlockEntity::new, RSBlocks.WIRELESS_TRANSMITTER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> STORAGE_MONITOR = REGISTRY.register("storage_monitor", () -> registerSynchronizationParameters(StorageMonitorBlockEntity.SPEC, BlockEntityType.Builder.of(StorageMonitorBlockEntity::new, RSBlocks.STORAGE_MONITOR.get()).build(null))); public static final DeferredHolder, BlockEntityType> CONSTRUCTOR = REGISTRY.register("constructor", () -> registerSynchronizationParameters(ConstructorBlockEntity.SPEC, BlockEntityType.Builder.of(ConstructorBlockEntity::new, RSBlocks.CONSTRUCTOR.get()).build(null))); public static final DeferredHolder, BlockEntityType> DESTRUCTOR = REGISTRY.register("destructor", () -> registerSynchronizationParameters(DestructorBlockEntity.SPEC, BlockEntityType.Builder.of(DestructorBlockEntity::new, RSBlocks.DESTRUCTOR.get()).build(null))); public static final DeferredHolder, BlockEntityType> DISK_MANIPULATOR = REGISTRY.register("disk_manipulator", () -> registerSynchronizationParameters(DiskManipulatorBlockEntity.SPEC, BlockEntityType.Builder.of(DiskManipulatorBlockEntity::new, RSBlocks.DISK_MANIPULATOR.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> PORTABLE_GRID = 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))); public static final DeferredHolder, BlockEntityType> CREATIVE_PORTABLE_GRID = 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))); public static final DeferredHolder, BlockEntityType> CRAFTER = REGISTRY.register("crafter", () -> registerSynchronizationParameters(CrafterBlockEntity.SPEC, BlockEntityType.Builder.of(CrafterBlockEntity::new, RSBlocks.CRAFTER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> CRAFTER_MANAGER = REGISTRY.register("crafter_manager", () -> registerSynchronizationParameters(CrafterManagerBlockEntity.SPEC, BlockEntityType.Builder.of(CrafterManagerBlockEntity::new, RSBlocks.CRAFTER_MANAGER.getBlocks()).build(null))); public static final DeferredHolder, BlockEntityType> CRAFTING_MONITOR = REGISTRY.register("crafting_monitor", () -> registerSynchronizationParameters(CraftingMonitorBlockEntity.SPEC, BlockEntityType.Builder.of(CraftingMonitorBlockEntity::new, RSBlocks.CRAFTING_MONITOR.getBlocks()).build(null))); private static BlockEntityType registerSynchronizationParameters(BlockEntitySynchronizationSpec spec, BlockEntityType t) { spec.getParameters().forEach(BlockEntitySynchronizationManager::registerParameter); return t; } private RSBlockEntities() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSBlocks.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.block.*; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import com.refinedmods.refinedstorage.util.BlockColorMap; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.tags.TagKey; import net.minecraft.world.level.block.Block; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; public final class RSBlocks { public static final DeferredHolder IMPORTER; public static final DeferredHolder EXPORTER; public static final DeferredHolder QUARTZ_ENRICHED_IRON; public static final DeferredHolder MACHINE_CASING; public static final DeferredHolder CABLE; public static final DeferredHolder DISK_DRIVE; public static final DeferredHolder EXTERNAL_STORAGE; public static final Map> STORAGE_BLOCKS = new EnumMap<>(ItemStorageType.class); public static final Map> FLUID_STORAGE_BLOCKS = new EnumMap<>(FluidStorageType.class); public static final Map, BlockColorMap> COLORED_BLOCK_TAGS = new HashMap<>(); public static final DeferredHolder INTERFACE; public static final DeferredHolder FLUID_INTERFACE; public static final DeferredHolder STORAGE_MONITOR; public static final DeferredHolder CONSTRUCTOR; public static final DeferredHolder DESTRUCTOR; public static final DeferredHolder PORTABLE_GRID; public static final DeferredHolder CREATIVE_PORTABLE_GRID; public static final List> COLORED_BLOCKS = new ArrayList<>(); private static final DeferredRegister BLOCKS = DeferredRegister.create(BuiltInRegistries.BLOCK, RS.ID); public static final BlockColorMap CRAFTER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap RELAY = new BlockColorMap<>(BLOCKS); public static final BlockColorMap NETWORK_TRANSMITTER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap NETWORK_RECEIVER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap CONTROLLER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap CREATIVE_CONTROLLER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap GRID = new BlockColorMap<>(BLOCKS); public static final BlockColorMap CRAFTING_GRID = new BlockColorMap<>(BLOCKS); public static final BlockColorMap PATTERN_GRID = new BlockColorMap<>(BLOCKS); public static final BlockColorMap FLUID_GRID = new BlockColorMap<>(BLOCKS); public static final BlockColorMap SECURITY_MANAGER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap WIRELESS_TRANSMITTER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap DISK_MANIPULATOR = new BlockColorMap<>(BLOCKS); public static final BlockColorMap CRAFTER_MANAGER = new BlockColorMap<>(BLOCKS); public static final BlockColorMap CRAFTING_MONITOR = new BlockColorMap<>(BLOCKS); public static final BlockColorMap DETECTOR = new BlockColorMap<>(BLOCKS); private static final String GRID_SUFFIX = "_grid"; static { QUARTZ_ENRICHED_IRON = BLOCKS.register("quartz_enriched_iron_block", QuartzEnrichedIronBlock::new); MACHINE_CASING = BLOCKS.register("machine_casing", MachineCasingBlock::new); CABLE = BLOCKS.register("cable", CableBlock::new); DISK_DRIVE = BLOCKS.register("disk_drive", DiskDriveBlock::new); EXTERNAL_STORAGE = BLOCKS.register("external_storage", ExternalStorageBlock::new); IMPORTER = BLOCKS.register("importer", ImporterBlock::new); EXPORTER = BLOCKS.register("exporter", ExporterBlock::new); INTERFACE = BLOCKS.register("interface", InterfaceBlock::new); FLUID_INTERFACE = BLOCKS.register("fluid_interface", FluidInterfaceBlock::new); STORAGE_MONITOR = BLOCKS.register("storage_monitor", StorageMonitorBlock::new); CONSTRUCTOR = BLOCKS.register("constructor", ConstructorBlock::new); DESTRUCTOR = BLOCKS.register("destructor", DestructorBlock::new); CREATIVE_PORTABLE_GRID = BLOCKS.register("creative_portable_grid", () -> new PortableGridBlock(PortableGridBlockItem.Type.CREATIVE)); PORTABLE_GRID = BLOCKS.register("portable_grid", () -> new PortableGridBlock(PortableGridBlockItem.Type.NORMAL)); for (ItemStorageType type : ItemStorageType.values()) { STORAGE_BLOCKS.put(type, BLOCKS.register(type.getName() + "_storage_block", () -> new StorageBlock(type))); } for (FluidStorageType type : FluidStorageType.values()) { FLUID_STORAGE_BLOCKS.put(type, BLOCKS.register(type.getName() + "_fluid_storage_block", () -> new FluidStorageBlock(type))); } GRID.registerBlocks("grid", () -> new GridBlock(GridType.NORMAL)); CRAFTING_GRID.registerBlocks(GridType.CRAFTING.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.CRAFTING)); PATTERN_GRID.registerBlocks(GridType.PATTERN.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.PATTERN)); FLUID_GRID.registerBlocks(GridType.FLUID.getSerializedName() + GRID_SUFFIX, () -> new GridBlock(GridType.FLUID)); CONTROLLER.registerBlocks("controller", () -> new ControllerBlock(NetworkType.NORMAL)); CREATIVE_CONTROLLER.registerBlocks("creative_controller", () -> new ControllerBlock(NetworkType.CREATIVE)); NETWORK_RECEIVER.registerBlocks("network_receiver", NetworkReceiverBlock::new); NETWORK_TRANSMITTER.registerBlocks("network_transmitter", NetworkTransmitterBlock::new); RELAY.registerBlocks("relay", RelayBlock::new); SECURITY_MANAGER.registerBlocks("security_manager", SecurityManagerBlock::new); WIRELESS_TRANSMITTER.registerBlocks("wireless_transmitter", WirelessTransmitterBlock::new); DISK_MANIPULATOR.registerBlocks("disk_manipulator", DiskManipulatorBlock::new); CRAFTER.registerBlocks("crafter", CrafterBlock::new); CRAFTER_MANAGER.registerBlocks("crafter_manager", CrafterManagerBlock::new); CRAFTING_MONITOR.registerBlocks("crafting_monitor", CraftingMonitorBlock::new); DETECTOR.registerBlocks("detector", DetectorBlock::new); } private RSBlocks() { } public static void register(IEventBus bus) { BLOCKS.register(bus); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSContainerMenus.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.blockentity.*; import com.refinedmods.refinedstorage.container.*; import com.refinedmods.refinedstorage.container.factory.*; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.inventory.MenuType; import net.neoforged.neoforge.common.extensions.IMenuTypeExtension; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; public final class RSContainerMenus { public static final DeferredRegister> REGISTRY = DeferredRegister.create(BuiltInRegistries.MENU, RS.ID); public static final DeferredHolder, MenuType> CONTROLLER = REGISTRY.register("controller", () -> IMenuTypeExtension.create(((windowId, inv, data) -> new ControllerContainerMenu(null, inv.player, windowId)))); public static final DeferredHolder, MenuType> GRID = REGISTRY.register("grid", () -> IMenuTypeExtension.create(new GridContainerFactory())); public static final DeferredHolder, MenuType> DETECTOR = REGISTRY.register("detector", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new DetectorContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> EXPORTER = REGISTRY.register("exporter", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new ExporterContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> EXTERNAL_STORAGE = REGISTRY.register("external_storage", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new ExternalStorageContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> FILTER = REGISTRY.register("filter", () -> IMenuTypeExtension.create((windowId, inv, data) -> new FilterContainerMenu(inv.player, inv.getSelected(), windowId))); public static final DeferredHolder, MenuType> IMPORTER = REGISTRY.register("importer", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new ImporterContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> NETWORK_TRANSMITTER = REGISTRY.register("network_transmitter", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new NetworkTransmitterContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> RELAY = REGISTRY.register("relay", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new RelayContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> DISK_DRIVE = REGISTRY.register("disk_drive", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new DiskDriveContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> STORAGE_BLOCK = REGISTRY.register("storage_block", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new StorageContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> FLUID_STORAGE_BLOCK = REGISTRY.register("fluid_storage_block", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new FluidStorageContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> SECURITY_MANAGER = REGISTRY.register("security_manager", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new SecurityManagerContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> INTERFACE = REGISTRY.register("interface", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new InterfaceContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> FLUID_INTERFACE = REGISTRY.register("fluid_interface", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new FluidInterfaceContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> WIRELESS_TRANSMITTER = REGISTRY.register("wireless_transmitter", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new WirelessTransmitterContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> STORAGE_MONITOR = REGISTRY.register("storage_monitor", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new StorageMonitorContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> CONSTRUCTOR = REGISTRY.register("constructor", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new ConstructorContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> DESTRUCTOR = REGISTRY.register("destructor", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new DestructorContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> DISK_MANIPULATOR = REGISTRY.register("disk_manipulator", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new DiskManipulatorContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> CRAFTER = REGISTRY.register("crafter", () -> IMenuTypeExtension.create(new BlockEntityContainerFactory((windowId, inv, blockEntity) -> new CrafterContainerMenu(blockEntity, inv.player, windowId)))); public static final DeferredHolder, MenuType> CRAFTER_MANAGER = REGISTRY.register("crafter_manager", () -> IMenuTypeExtension.create(new CrafterManagerContainerFactory())); public static final DeferredHolder, MenuType> CRAFTING_MONITOR = REGISTRY.register("crafting_monitor", () -> IMenuTypeExtension.create(new CraftingMonitorContainerFactory())); public static final DeferredHolder, MenuType> WIRELESS_CRAFTING_MONITOR = REGISTRY.register("wireless_crafting_monitor", () -> IMenuTypeExtension.create(new WirelessCraftingMonitorContainerFactory())); private RSContainerMenus() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSCreativeModeTabItems.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.item.*; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.*; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.RegisterEvent; public class RSCreativeModeTabItems { private RSCreativeModeTabItems() { } public static void register(RegisterEvent.RegisterHelper helper) { helper.register(new ResourceLocation(RS.ID, "general"), CreativeModeTab.builder() .title(Component.translatable("itemGroup.refinedstorage")) .icon(() -> new ItemStack(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get())) .displayItems((params, output) -> RSCreativeModeTabItems.append(output)) .build()); } public static void append(CreativeModeTab.Output output) { add(output, RSItems.CONSTRUCTION_CORE); add(output, RSItems.DESTRUCTION_CORE); add(output, RSItems.QUARTZ_ENRICHED_IRON); add(output, RSItems.PROCESSOR_BINDING); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_BASIC)); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_IMPROVED)); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.RAW_ADVANCED)); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.BASIC)); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.IMPROVED)); add(output, RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED)); add(output, RSItems.SILICON); add(output, RSItems.SECURITY_CARD); add(output, RSItems.NETWORK_CARD); add(output, ItemStorageType.ONE_K); add(output, ItemStorageType.FOUR_K); add(output, ItemStorageType.SIXTEEN_K); add(output, ItemStorageType.SIXTY_FOUR_K); add(output, ItemStorageType.CREATIVE); add(output, FluidStorageType.SIXTY_FOUR_K); add(output, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K); add(output, FluidStorageType.THOUSAND_TWENTY_FOUR_K); add(output, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K); add(output, FluidStorageType.CREATIVE); add(output, RSItems.STORAGE_HOUSING); add(output, UpgradeItem.Type.NORMAL); add(output, UpgradeItem.Type.SPEED); add(output, UpgradeItem.Type.RANGE); add(output, UpgradeItem.Type.CRAFTING); add(output, UpgradeItem.Type.STACK); add(output, UpgradeItem.Type.SILK_TOUCH); add(output, UpgradeItem.Type.FORTUNE_1); add(output, UpgradeItem.Type.FORTUNE_2); add(output, UpgradeItem.Type.FORTUNE_3); add(output, UpgradeItem.Type.REGULATOR); add(output, RSItems.WRENCH); add(output, RSItems.PATTERN); add(output, RSItems.FILTER); add(output, RSItems.WIRELESS_GRID); add(output, RSItems.CREATIVE_WIRELESS_GRID); add(output, RSItems.WIRELESS_FLUID_GRID); add(output, RSItems.CREATIVE_WIRELESS_FLUID_GRID); add(output, RSItems.WIRELESS_CRAFTING_MONITOR); add(output, RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR); add(output, RSItems.PORTABLE_GRID); add(output, RSItems.CREATIVE_PORTABLE_GRID); add(output, RSItems.QUARTZ_ENRICHED_IRON_BLOCK); add(output, RSItems.MACHINE_CASING); add(output, RSItems.CABLE); add(output, RSItems.DISK_DRIVE); addStorageBlock(output, ItemStorageType.ONE_K); addStorageBlock(output, ItemStorageType.FOUR_K); addStorageBlock(output, ItemStorageType.SIXTEEN_K); addStorageBlock(output, ItemStorageType.SIXTY_FOUR_K); addStorageBlock(output, ItemStorageType.CREATIVE); addStorageBlock(output, FluidStorageType.SIXTY_FOUR_K); addStorageBlock(output, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K); addStorageBlock(output, FluidStorageType.THOUSAND_TWENTY_FOUR_K); addStorageBlock(output, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K); addStorageBlock(output, FluidStorageType.CREATIVE); add(output, RSItems.EXTERNAL_STORAGE); add(output, RSItems.IMPORTER); add(output, RSItems.EXPORTER); add(output, RSItems.INTERFACE); add(output, RSItems.FLUID_INTERFACE); add(output, RSItems.STORAGE_MONITOR); add(output, RSItems.CONSTRUCTOR); add(output, RSItems.DESTRUCTOR); add(output, RSItems.CONTROLLER); add(output, RSItems.CREATIVE_CONTROLLER); add(output, RSItems.GRID); add(output, RSItems.CRAFTING_GRID); add(output, RSItems.PATTERN_GRID); add(output, RSItems.FLUID_GRID); add(output, RSItems.NETWORK_RECEIVER); add(output, RSItems.NETWORK_TRANSMITTER); add(output, RSItems.RELAY); add(output, RSItems.DETECTOR); add(output, RSItems.SECURITY_MANAGER); add(output, RSItems.WIRELESS_TRANSMITTER); add(output, RSItems.DISK_MANIPULATOR); add(output, RSItems.CRAFTER); add(output, RSItems.CRAFTER_MANAGER); add(output, RSItems.CRAFTING_MONITOR); addCovers(output); } private static void addCovers(CreativeModeTab.Output output) { if (!RS.CLIENT_CONFIG.getCover().showAllRecipesInJEI()) { ItemStack coverExampleStack = new ItemStack(Blocks.STONE_BRICKS); addCovers(output, coverExampleStack); return; } for (Block block : BuiltInRegistries.BLOCK) { Item item = Item.byBlock(block); if (item == Items.AIR) { continue; } ItemStack itemStack = new ItemStack(item); if (CoverManager.isValidCover(itemStack)) { addCovers(output, itemStack); } } } private static void addCovers(CreativeModeTab.Output output, ItemStack coverExampleStack) { ItemStack coverStack = new ItemStack(RSItems.COVER.get()); ItemStack hollowCoverStack = new ItemStack(RSItems.HOLLOW_COVER.get()); CoverItem.setItem(coverStack, coverExampleStack); CoverItem.setItem(hollowCoverStack, coverExampleStack); output.accept(coverStack); output.accept(hollowCoverStack); } private static void add(CreativeModeTab.Output output, ColorMap cm) { cm.values().forEach(c -> add(output, c)); } private static void add(CreativeModeTab.Output output, ItemStorageType type) { DeferredHolder part = RSItems.ITEM_STORAGE_PARTS.get(type); if (part != null) { add(output, part); } add(output, RSItems.ITEM_STORAGE_DISKS.get(type)); } private static void addStorageBlock(CreativeModeTab.Output output, ItemStorageType type) { add(output, RSItems.STORAGE_BLOCKS.get(type)); } private static void addStorageBlock(CreativeModeTab.Output output, FluidStorageType type) { add(output, RSItems.FLUID_STORAGE_BLOCKS.get(type)); } private static void add(CreativeModeTab.Output output, FluidStorageType type) { DeferredHolder part = RSItems.FLUID_STORAGE_PARTS.get(type); if (part != null) { add(output, part); } add(output, RSItems.FLUID_STORAGE_DISKS.get(type)); } private static void add(CreativeModeTab.Output output, UpgradeItem.Type type) { add(output, RSItems.UPGRADE_ITEMS.get(type)); } private static void add(CreativeModeTab.Output output, DeferredHolder ro) { output.accept(ro.get()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSItems.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.item.CoreItem; import com.refinedmods.refinedstorage.item.CoverItem; import com.refinedmods.refinedstorage.item.FilterItem; import com.refinedmods.refinedstorage.item.FluidStorageDiskItem; import com.refinedmods.refinedstorage.item.FluidStoragePartItem; import com.refinedmods.refinedstorage.item.HollowCoverItem; import com.refinedmods.refinedstorage.item.NetworkCardItem; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.item.ProcessorBindingItem; import com.refinedmods.refinedstorage.item.ProcessorItem; import com.refinedmods.refinedstorage.item.QuartzEnrichedIronItem; import com.refinedmods.refinedstorage.item.SecurityCardItem; import com.refinedmods.refinedstorage.item.SiliconItem; import com.refinedmods.refinedstorage.item.StorageDiskItem; import com.refinedmods.refinedstorage.item.StorageHousingItem; import com.refinedmods.refinedstorage.item.StoragePartItem; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem; import com.refinedmods.refinedstorage.item.WirelessFluidGridItem; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.item.WrenchItem; import com.refinedmods.refinedstorage.item.blockitem.BaseBlockItem; import com.refinedmods.refinedstorage.item.blockitem.ControllerBlockItem; import com.refinedmods.refinedstorage.item.blockitem.FluidStorageBlockItem; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import com.refinedmods.refinedstorage.item.blockitem.StorageBlockItem; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.ColorMap; import com.refinedmods.refinedstorage.util.ItemColorMap; import java.util.ArrayList; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.neoforged.bus.api.IEventBus; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; public final class RSItems { public static final DeferredRegister ITEMS = DeferredRegister.create(BuiltInRegistries.ITEM, RS.ID); public static final DeferredHolder QUARTZ_ENRICHED_IRON; public static final DeferredHolder SILICON; public static final DeferredHolder PROCESSOR_BINDING; public static final DeferredHolder WRENCH; public static final DeferredHolder PATTERN; public static final DeferredHolder FILTER; public static final DeferredHolder STORAGE_HOUSING; public static final DeferredHolder NETWORK_CARD; public static final DeferredHolder SECURITY_CARD; public static final DeferredHolder CONSTRUCTION_CORE; public static final DeferredHolder DESTRUCTION_CORE; public static final DeferredHolder WIRELESS_GRID; public static final DeferredHolder CREATIVE_WIRELESS_GRID; public static final DeferredHolder WIRELESS_FLUID_GRID; public static final DeferredHolder CREATIVE_WIRELESS_FLUID_GRID; public static final DeferredHolder PORTABLE_GRID; public static final DeferredHolder CREATIVE_PORTABLE_GRID; public static final DeferredHolder WIRELESS_CRAFTING_MONITOR; public static final DeferredHolder CREATIVE_WIRELESS_CRAFTING_MONITOR; public static final DeferredHolder MACHINE_CASING; public static final DeferredHolder COVER; public static final DeferredHolder HOLLOW_COVER; public static final DeferredHolder QUARTZ_ENRICHED_IRON_BLOCK; public static final DeferredHolder CABLE; public static final DeferredHolder DISK_DRIVE; public static final DeferredHolder EXTERNAL_STORAGE; public static final DeferredHolder IMPORTER; public static final DeferredHolder EXPORTER; public static final DeferredHolder INTERFACE; public static final DeferredHolder FLUID_INTERFACE; public static final DeferredHolder STORAGE_MONITOR; public static final DeferredHolder CONSTRUCTOR; public static final DeferredHolder DESTRUCTOR; public static final Map> PROCESSORS = new EnumMap<>(ProcessorItem.Type.class); public static final Map> ITEM_STORAGE_PARTS = new EnumMap<>(ItemStorageType.class); public static final Map> ITEM_STORAGE_DISKS = new EnumMap<>(ItemStorageType.class); public static final Map> STORAGE_BLOCKS = new EnumMap<>(ItemStorageType.class); public static final Map> FLUID_STORAGE_PARTS = new EnumMap<>(FluidStorageType.class); public static final Map> FLUID_STORAGE_DISKS = new EnumMap<>(FluidStorageType.class); public static final Map> FLUID_STORAGE_BLOCKS = new EnumMap<>(FluidStorageType.class); public static final Map> UPGRADE_ITEMS = new EnumMap<>(UpgradeItem.Type.class); public static final Map, ColorMap> COLORED_ITEM_TAGS = new HashMap<>(); private static final List LATE_REGISTRATION = new ArrayList<>(); public static final ItemColorMap CRAFTER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap RELAY = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap NETWORK_TRANSMITTER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap NETWORK_RECEIVER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ColorMap CONTROLLER = new ColorMap<>(ITEMS, LATE_REGISTRATION); public static final ColorMap CREATIVE_CONTROLLER = new ColorMap<>(ITEMS, LATE_REGISTRATION); public static final ItemColorMap GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap CRAFTING_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap PATTERN_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap FLUID_GRID = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap SECURITY_MANAGER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap WIRELESS_TRANSMITTER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap DISK_MANIPULATOR = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap CRAFTER_MANAGER = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap CRAFTING_MONITOR = new ItemColorMap(ITEMS, LATE_REGISTRATION); public static final ItemColorMap DETECTOR = new ItemColorMap(ITEMS, LATE_REGISTRATION); static { CONSTRUCTION_CORE = ITEMS.register("construction_core", CoreItem::new); DESTRUCTION_CORE = ITEMS.register("destruction_core", CoreItem::new); QUARTZ_ENRICHED_IRON = ITEMS.register("quartz_enriched_iron", QuartzEnrichedIronItem::new); PROCESSOR_BINDING = ITEMS.register("processor_binding", ProcessorBindingItem::new); for (ProcessorItem.Type type : ProcessorItem.Type.values()) { PROCESSORS.put(type, ITEMS.register(type.getName() + "_processor", ProcessorItem::new)); } SILICON = ITEMS.register("silicon", SiliconItem::new); SECURITY_CARD = ITEMS.register("security_card", SecurityCardItem::new); NETWORK_CARD = ITEMS.register("network_card", NetworkCardItem::new); for (ItemStorageType type : ItemStorageType.values()) { if (type != ItemStorageType.CREATIVE) { ITEM_STORAGE_PARTS.put(type, ITEMS.register(type.getName() + "_storage_part", StoragePartItem::new)); } ITEM_STORAGE_DISKS.put(type, ITEMS.register(type.getName() + "_storage_disk", () -> new StorageDiskItem(type))); } for (FluidStorageType type : FluidStorageType.values()) { if (type != FluidStorageType.CREATIVE) { FLUID_STORAGE_PARTS.put(type, ITEMS.register(type.getName() + "_fluid_storage_part", FluidStoragePartItem::new)); } FLUID_STORAGE_DISKS.put(type, ITEMS.register(type.getName() + "_fluid_storage_disk", () -> new FluidStorageDiskItem(type))); } STORAGE_HOUSING = ITEMS.register("storage_housing", StorageHousingItem::new); for (UpgradeItem.Type type : UpgradeItem.Type.values()) { UPGRADE_ITEMS.put(type, ITEMS.register(type == UpgradeItem.Type.NORMAL ? "upgrade" : type.getName() + "_upgrade", () -> new UpgradeItem(type))); } WRENCH = ITEMS.register("wrench", WrenchItem::new); PATTERN = ITEMS.register("pattern", PatternItem::new); FILTER = ITEMS.register("filter", FilterItem::new); PORTABLE_GRID = ITEMS.register("portable_grid", () -> new PortableGridBlockItem(PortableGridBlockItem.Type.NORMAL)); CREATIVE_PORTABLE_GRID = ITEMS.register("creative_portable_grid", () -> new PortableGridBlockItem(PortableGridBlockItem.Type.CREATIVE)); QUARTZ_ENRICHED_IRON_BLOCK = registerBlockItemFor(RSBlocks.QUARTZ_ENRICHED_IRON); MACHINE_CASING = registerBlockItemFor(RSBlocks.MACHINE_CASING); COVER = ITEMS.register("cover", CoverItem::new); HOLLOW_COVER = ITEMS.register("hollow_cover", HollowCoverItem::new); CABLE = registerBlockItemFor(RSBlocks.CABLE); DISK_DRIVE = registerBlockItemFor(RSBlocks.DISK_DRIVE); for (ItemStorageType type : ItemStorageType.values()) { STORAGE_BLOCKS.put(type, ITEMS.register(RSBlocks.STORAGE_BLOCKS.get(type).getId().getPath(), () -> new StorageBlockItem(RSBlocks.STORAGE_BLOCKS.get(type).get()))); } for (FluidStorageType type : FluidStorageType.values()) { FLUID_STORAGE_BLOCKS.put(type, ITEMS.register(RSBlocks.FLUID_STORAGE_BLOCKS.get(type).getId().getPath(), () -> new FluidStorageBlockItem(RSBlocks.FLUID_STORAGE_BLOCKS.get(type).get()))); } EXTERNAL_STORAGE = registerBlockItemFor(RSBlocks.EXTERNAL_STORAGE); IMPORTER = registerBlockItemFor(RSBlocks.IMPORTER); EXPORTER = registerBlockItemFor(RSBlocks.EXPORTER); INTERFACE = registerBlockItemFor(RSBlocks.INTERFACE); FLUID_INTERFACE = registerBlockItemFor(RSBlocks.FLUID_INTERFACE); STORAGE_MONITOR = registerBlockItemFor(RSBlocks.STORAGE_MONITOR); CONSTRUCTOR = registerBlockItemFor(RSBlocks.CONSTRUCTOR); DESTRUCTOR = registerBlockItemFor(RSBlocks.DESTRUCTOR); CONTROLLER.put(ColorMap.DEFAULT_COLOR, ITEMS.register( RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath(), () -> new ControllerBlockItem( RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get(), ColorMap.DEFAULT_COLOR, BlockUtils.getBlockTranslation(RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get()) ) )); CREATIVE_CONTROLLER.put(ColorMap.DEFAULT_COLOR, ITEMS.register( RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath(), () -> new ControllerBlockItem( RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get(), ColorMap.DEFAULT_COLOR, BlockUtils.getBlockTranslation(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get()) ) )); COLORED_ITEM_TAGS.put( ItemTags.create(new ResourceLocation(RS.ID, CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath())), CONTROLLER ); LATE_REGISTRATION.add(() -> { RSBlocks.CONTROLLER.forEach((color, block) -> { if (color != ColorMap.DEFAULT_COLOR) { CONTROLLER.put(color, ITEMS.register(RSBlocks.CONTROLLER.get(color).getId().getPath(), () -> new ControllerBlockItem(RSBlocks.CONTROLLER.get(color).get(), color, Component.translatable( RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get().getDescriptionId())))); } }); RSBlocks.CREATIVE_CONTROLLER.forEach((color, block) -> { if (color != ColorMap.DEFAULT_COLOR) { CREATIVE_CONTROLLER.put(color, ITEMS.register(RSBlocks.CREATIVE_CONTROLLER.get(color).getId().getPath(), () -> new ControllerBlockItem(RSBlocks.CREATIVE_CONTROLLER.get(color).get(), color, Component.translatable(RSBlocks.CREATIVE_CONTROLLER.get(ColorMap.DEFAULT_COLOR).get() .getDescriptionId())))); } }); }); GRID.registerItemsFromBlocks(RSBlocks.GRID); CRAFTING_GRID.registerItemsFromBlocks(RSBlocks.CRAFTING_GRID); PATTERN_GRID.registerItemsFromBlocks(RSBlocks.PATTERN_GRID); FLUID_GRID.registerItemsFromBlocks(RSBlocks.FLUID_GRID); NETWORK_RECEIVER.registerItemsFromBlocks(RSBlocks.NETWORK_RECEIVER); NETWORK_TRANSMITTER.registerItemsFromBlocks(RSBlocks.NETWORK_TRANSMITTER); RELAY.registerItemsFromBlocks(RSBlocks.RELAY); DETECTOR.registerItemsFromBlocks(RSBlocks.DETECTOR); SECURITY_MANAGER.registerItemsFromBlocks(RSBlocks.SECURITY_MANAGER); WIRELESS_TRANSMITTER.registerItemsFromBlocks(RSBlocks.WIRELESS_TRANSMITTER); DISK_MANIPULATOR.registerItemsFromBlocks(RSBlocks.DISK_MANIPULATOR); CRAFTER.registerItemsFromBlocks(RSBlocks.CRAFTER); CRAFTER_MANAGER.registerItemsFromBlocks(RSBlocks.CRAFTER_MANAGER); CRAFTING_MONITOR.registerItemsFromBlocks(RSBlocks.CRAFTING_MONITOR); WIRELESS_GRID = ITEMS.register("wireless_grid", () -> new WirelessGridItem(WirelessGridItem.Type.NORMAL)); CREATIVE_WIRELESS_GRID = ITEMS.register("creative_wireless_grid", () -> new WirelessGridItem(WirelessGridItem.Type.CREATIVE)); WIRELESS_FLUID_GRID = ITEMS.register("wireless_fluid_grid", () -> new WirelessFluidGridItem(WirelessFluidGridItem.Type.NORMAL)); CREATIVE_WIRELESS_FLUID_GRID = ITEMS.register("creative_wireless_fluid_grid", () -> new WirelessFluidGridItem(WirelessFluidGridItem.Type.CREATIVE)); WIRELESS_CRAFTING_MONITOR = ITEMS.register("wireless_crafting_monitor", () -> new WirelessCraftingMonitorItem(WirelessCraftingMonitorItem.Type.NORMAL)); CREATIVE_WIRELESS_CRAFTING_MONITOR = ITEMS.register("creative_wireless_crafting_monitor", () -> new WirelessCraftingMonitorItem(WirelessCraftingMonitorItem.Type.CREATIVE)); LATE_REGISTRATION.forEach(Runnable::run); } private RSItems() { } private static DeferredHolder registerBlockItemFor( DeferredHolder block) { return ITEMS.register(block.getId().getPath(), () -> new BaseBlockItem(block.get(), new Item.Properties())); } public static void register(IEventBus bus) { ITEMS.register(bus); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSKeyBindings.java ================================================ package com.refinedmods.refinedstorage; import com.mojang.blaze3d.platform.InputConstants; import net.minecraft.client.KeyMapping; import net.neoforged.neoforge.client.settings.KeyConflictContext; import net.neoforged.neoforge.client.settings.KeyModifier; import org.lwjgl.glfw.GLFW; public final class RSKeyBindings { public static final KeyMapping FOCUS_SEARCH_BAR = new KeyMapping( "key.refinedstorage.focusSearchBar", KeyConflictContext.GUI, InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_TAB, RS.NAME ); public static final KeyMapping CLEAR_GRID_CRAFTING_MATRIX = new KeyMapping( "key.refinedstorage.clearGridCraftingMatrix", KeyConflictContext.GUI, KeyModifier.CONTROL, InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_X, RS.NAME ); public static final KeyMapping OPEN_WIRELESS_GRID = new KeyMapping( "key.refinedstorage.openWirelessGrid", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, RS.NAME ); public static final KeyMapping OPEN_WIRELESS_FLUID_GRID = new KeyMapping( "key.refinedstorage.openWirelessFluidGrid", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, RS.NAME ); public static final KeyMapping OPEN_WIRELESS_CRAFTING_MONITOR = new KeyMapping( "key.refinedstorage.openWirelessCraftingMonitor", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, RS.NAME ); public static final KeyMapping OPEN_PORTABLE_GRID = new KeyMapping( "key.refinedstorage.openPortableGrid", KeyConflictContext.IN_GAME, InputConstants.UNKNOWN, RS.NAME ); private RSKeyBindings() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSLootFunctions.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.loottable.ControllerLootFunction; import com.refinedmods.refinedstorage.loottable.CrafterLootFunction; import com.refinedmods.refinedstorage.loottable.PortableGridBlockLootFunction; import com.refinedmods.refinedstorage.loottable.StorageBlockLootFunction; import com.mojang.serialization.Codec; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; public final class RSLootFunctions { public static LootItemFunctionType STORAGE_BLOCK; public static LootItemFunctionType PORTABLE_GRID; public static LootItemFunctionType CRAFTER; public static LootItemFunctionType CONTROLLER; private RSLootFunctions() { } public static void register() { STORAGE_BLOCK = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, "storage_block"), new LootItemFunctionType(Codec.unit(new StorageBlockLootFunction()))); PORTABLE_GRID = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, "portable_grid"), new LootItemFunctionType( Codec.unit(new PortableGridBlockLootFunction()))); CRAFTER = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, "crafter"), new LootItemFunctionType(Codec.unit(new CrafterLootFunction()))); CONTROLLER = Registry.register(BuiltInRegistries.LOOT_FUNCTION_TYPE, new ResourceLocation(RS.ID, "controller"), new LootItemFunctionType(Codec.unit(new ControllerLootFunction()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/RSRecipeSerializers.java ================================================ package com.refinedmods.refinedstorage; import com.refinedmods.refinedstorage.recipe.CoverRecipe; import com.refinedmods.refinedstorage.recipe.HollowCoverRecipe; import com.refinedmods.refinedstorage.recipe.UpgradeWithEnchantedBookRecipeSerializer; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.crafting.RecipeSerializer; import net.neoforged.neoforge.registries.DeferredRegister; public final class RSRecipeSerializers { public static final DeferredRegister> REGISTRY = DeferredRegister.create(BuiltInRegistries.RECIPE_SERIALIZER, RS.ID); static { REGISTRY.register("upgrade_with_enchanted_book", UpgradeWithEnchantedBookRecipeSerializer::new); REGISTRY.register("cover_recipe", () -> CoverRecipe.SERIALIZER); REGISTRY.register("hollow_cover_recipe", () -> HollowCoverRecipe.SERIALIZER); } private RSRecipeSerializers() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/IRSAPI.java ================================================ package com.refinedmods.refinedstorage.api; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry; import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior; import com.refinedmods.refinedstorage.api.network.grid.IGridManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IQuantityFormatter; import com.refinedmods.refinedstorage.api.util.IStackList; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Set; /** * Represents a Refined Storage API implementation. * Delivered by the {@link RSAPIInject} annotation. */ public interface IRSAPI { /** * @return the comparer */ @Nonnull IComparer getComparer(); /** * @return the quantity formatter */ @Nonnull IQuantityFormatter getQuantityFormatter(); /** * @return the network node factory */ @Nonnull INetworkNodeRegistry getNetworkNodeRegistry(); /** * Gets a network node manager for a given level. * * @param level level * @return the network node manager for a given level */ INetworkNodeManager getNetworkNodeManager(ServerLevel level); /** * Gets a network manager for a given level. * * @param level level * @return the network manager for a given level */ INetworkManager getNetworkManager(ServerLevel level); /** * @return the crafting task registry */ @Nonnull ICraftingTaskRegistry getCraftingTaskRegistry(); /** * @return the crafting monitor element registry */ @Nonnull ICraftingMonitorElementRegistry getCraftingMonitorElementRegistry(); /** * @return the crafting preview element registry */ @Nonnull ICraftingPreviewElementRegistry getCraftingPreviewElementRegistry(); /** * @return an empty item stack list */ @Nonnull IStackList createItemStackList(); /** * @return an empty fluid stack list */ @Nonnull IStackList createFluidStackList(); /** * @return an empty crafting monitor element list */ @Nonnull ICraftingMonitorElementList createCraftingMonitorElementList(); /** * @return the grid manager */ @Nonnull IGridManager getGridManager(); /** * @return the default crafting grid behavior */ @Nonnull ICraftingGridBehavior getCraftingGridBehavior(); /** * @return the storage disk registry */ @Nonnull IStorageDiskRegistry getStorageDiskRegistry(); /** * @param level any level associated with the server * @return the storage disk manager */ @Nonnull IStorageDiskManager getStorageDiskManager(ServerLevel level); /** * @return the storage disk sync manager */ @Nonnull IStorageDiskSync getStorageDiskSync(); /** * @return the storage tracker manager */ @Nonnull IStorageTrackerManager getStorageTrackerManager(ServerLevel level); /** * Adds an external storage provider for the given storage type. * * @param type the storage type * @param provider the external storage provider */ void addExternalStorageProvider(StorageType type, IExternalStorageProvider provider); /** * @param type the type * @return a set of external storage providers */ Set> getExternalStorageProviders(StorageType type); /** * @param level the level * @param capacity the capacity * @param owner the owner or null if no owner * @return a storage disk */ @Nonnull IStorageDisk createDefaultItemDisk(ServerLevel level, int capacity, @Nullable Player owner); /** * @param level the level * @param capacity the capacity in mB * @param owner the owner or null if no owner * @return a fluid storage disk */ @Nonnull IStorageDisk createDefaultFluidDisk(ServerLevel level, int capacity, @Nullable Player owner); /** * Creates crafting request info for an item. * * @param stack the stack * @param count the count * @return the request info */ ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack, int count); /** * Creates crafting request info for a fluid. * * @param stack the stack * @param count the count * @return the request info */ ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack, int count); /** * Creates crafting request info from NBT. * * @param tag the nbt tag * @return the request info */ ICraftingRequestInfo createCraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException; /** * @param renderHandler the render handler to add */ void addPatternRenderHandler(ICraftingPatternRenderHandler renderHandler); /** * @return a list of pattern render handlers */ List getPatternRenderHandlers(); /** * @param stack the stack * @return a hashcode for the given stack */ int getItemStackHashCode(ItemStack stack); /** * @param stack the stack * @return a hashcode for the given stack */ int getFluidStackHashCode(FluidStack stack); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/RSAPIInject.java ================================================ package com.refinedmods.refinedstorage.api; import java.lang.annotation.ElementType; import java.lang.annotation.Target; /** * Needs to be implemented on a public static {@link IRSAPI} field. */ @Target(ElementType.FIELD) public @interface RSAPIInject { } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingManager.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener; import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; /** * The crafting manager handles the storing, updating, adding and deleting of crafting tasks in a network. */ public interface ICraftingManager { /** * @return the crafting tasks in this network, do NOT modify this */ Collection getTasks(); /** * Returns a crafting task by id. * * @param id the id * @return the task, or null if no task was found for the given id */ @Nullable ICraftingTask getTask(UUID id); /** * @return named crafting pattern containers */ Map> getNamedContainers(); /** * Starts a crafting task. * * @param task the task to start */ void start(@Nonnull ICraftingTask task); /** * Cancels a crafting task. * * @param id the id of the task to cancel, or null to cancel all */ void cancel(@Nullable UUID id); /** * Creates a crafting task for a given stack, but doesn't add it to the list. * * @param stack the stack to craft * @param quantity the quantity to craft * @return the calculation result */ ICalculationResult create(ItemStack stack, int quantity); /** * Creates a crafting task for a given stack, but doesn't add it to the list. * * @param stack the stack to craft * @param quantity the quantity to craft * @return the calculation result */ ICalculationResult create(FluidStack stack, int quantity); /** * Schedules a crafting task if the task isn't scheduled yet. * * @param source the source * @param stack the stack * @param amount the amount of items to request * @return the crafting task created, or null if no task is created */ @Nullable ICraftingTask request(Object source, ItemStack stack, int amount); /** * Schedules a crafting task if the task isn't scheduled yet. * * @param source the source * @param stack the stack * @param amount the mB of the fluid to request * @return the crafting task created, or null if no task is created */ @Nullable ICraftingTask request(Object source, FluidStack stack, int amount); /** * Tracks an incoming stack. * * @param stack the stack, can be empty */ int track(@Nonnull ItemStack stack, int size); /** * Tracks an incoming stack. * * @param stack the stack, can be empty */ int track(@Nonnull FluidStack stack, int size); /** * @return the crafting patterns in this network */ List getPatterns(); /** * Rebuilds the pattern list. */ void invalidate(); /** * Return a crafting pattern from an item stack. * * @param pattern the stack to get a pattern for * @return the crafting pattern, or null if none is found */ @Nullable ICraftingPattern getPattern(ItemStack pattern); /** * Return a crafting pattern from a fluid stack. * * @param pattern the stack to get a pattern for * @return the crafting pattern, or null if none is found */ @Nullable ICraftingPattern getPattern(FluidStack pattern); /** * Updates the tasks in this manager. */ void update(); /** * @param tag the tag to read from */ void readFromNbt(CompoundTag tag); /** * @param tag the tag to write to * @return the written tag */ CompoundTag writeToNbt(CompoundTag tag); /** * @param listener the listener */ void addListener(ICraftingMonitorListener listener); /** * @param listener the listener */ void removeListener(ICraftingMonitorListener listener); /** * Calls all {@link ICraftingMonitorListener}s. */ void onTaskChanged(); /** * @param pattern pattern to look for * @return a set with all containers that have this pattern */ Set getAllContainers(ICraftingPattern pattern); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPattern.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.List; /** * Represents a crafting pattern. */ public interface ICraftingPattern { /** * @return the {@link ICraftingPatternContainer} where the pattern is in */ ICraftingPatternContainer getContainer(); /** * @return the crafting pattern stack */ ItemStack getStack(); /** * @return true if the crafting pattern is valid, false otherwise */ boolean isValid(); /** * @return an error message when this pattern is not valid, or null if there's no message */ @Nullable Component getErrorMessage(); /** * @return true if the crafting pattern can be treated as a processing pattern, false otherwise */ boolean isProcessing(); /** * @return the inputs per slot */ List> getInputs(); /** * @return the outputs */ NonNullList getOutputs(); /** * @param took the items took per slot * @param registryAccess the registry accessor * @return the output based on the items took */ ItemStack getOutput(NonNullList took, RegistryAccess registryAccess); /** * @return the byproducts */ NonNullList getByproducts(); /** * @param took the items took per slot * @return the byproducts based on the items took */ NonNullList getByproducts(NonNullList took); /** * @return the fluid inputs per slot */ List> getFluidInputs(); /** * @return the fluid outputs */ NonNullList getFluidOutputs(); /** * @return the id of the factory that creates a crafting task for this pattern, as defined in the {@link ICraftingTaskRegistry} */ ResourceLocation getCraftingTaskFactoryId(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternContainer.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting; import com.refinedmods.refinedstorage.api.util.Action; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import org.apache.logging.log4j.LogManager; import javax.annotation.Nullable; import java.util.*; import java.util.stream.Collectors; import java.util.stream.IntStream; /** * Represents a network node that contains crafting patterns. */ public interface ICraftingPatternContainer { /** * Returns the interval of when a crafting step with a pattern in this container can update. * Minimum value is 0 (each tick). *

* Note: rather than maxing out the update interval, implementors might want to balance around {@link #getMaximumSuccessfulCraftingUpdates()}. * This method merely speeds up the update rate, it might be more interesting to increase the output rate in {@link #getMaximumSuccessfulCraftingUpdates()}. * * @return the update interval */ default int getUpdateInterval() { return 10; } /** * Returns the amount of successful crafting updates that this container can have per crafting step update. * If this limit is reached, crafting patterns from this container won't be able to update until the next * eligible crafting step update interval from {@link #getUpdateInterval()}. * * @return the maximum amount of successful crafting updates */ default int getMaximumSuccessfulCraftingUpdates() { return 1; } /** * @return the inventory that this container is connected to, or null if no inventory is present */ @Nullable IItemHandler getConnectedInventory(); /** * @return the fluid inventory that this container is connected to, or null if no fluid inventory is present */ @Nullable IFluidHandler getConnectedFluidInventory(); /** * @return the block entity that this container is connected to, or null if no block entity is present */ @Nullable BlockEntity getConnectedBlockEntity(); /** * @return the block entity that this container is facing */ BlockEntity getFacingBlockEntity(); /** * @return the direction to the facing block entity */ Direction getDirection(); /** * @return the patterns stored in this container */ List getPatterns(); /** * @return the pattern inventory, or null if no pattern inventory is present */ @Nullable IItemHandlerModifiable getPatternInventory(); /** * The name of this container for categorizing in the Crafting Manager GUI. * Will return the name of the root container if we're in a chained scenario. * * @return the name of this container */ Component getName(); /** * The custom name of this container, as set in an anvil for example. * Can be null. * * @return the name of this container */ @Nullable default Component getCustomName() { return null; } /** * @return the position of this container */ BlockPos getPosition(); /** * Containers may be daisy-chained together. If this container points to * another one, gets the root container in the chain. If containers are * not daisy-chained, returns this container. If there was a container * loop, returns null. * * @return the root pattern container */ @Nullable ICraftingPatternContainer getRootContainer(); /** * @return the UUID of this container */ UUID getUuid(); /** * @return true if the connected inventory is locked for processing patterns, false otherwise */ default boolean isLocked() { return false; } /** * Unlock the container so it may be used by processing pattern */ void unlock(); /** * Called when this container is used by a processing pattern to insert items or fluids in the connected inventory. */ default void onUsedForProcessing() { } /** * @return whether the container is successfully connected to the inventory it wants to insert to */ default boolean hasConnectedInventory() { return getConnectedInventory() != null; } /** * @return whether the container is successfully connected to the fluid inventory it wants to insert to */ default boolean hasConnectedFluidInventory() { return getConnectedFluidInventory() != null; } /** * Called by Autocrafting when it uses this crafter in a processing recipe that has items as input * * @param toInsert Collection of Itemstack stacklist entries to insert into the inventory * @param action action to perform * @return whether insertion was successful */ default boolean insertItemsIntoInventory(Collection toInsert, Action action) { IItemHandler dest = getConnectedInventory(); if (toInsert.isEmpty()) { return true; } if (dest == null) { return false; } Deque stacks = new ArrayDeque<>(toInsert); ItemStack current = stacks.poll(); List availableSlots = IntStream.range(0, dest.getSlots()).boxed().collect(Collectors.toList()); while (current != null && !availableSlots.isEmpty()) { ItemStack remainder = ItemStack.EMPTY; for (int i = 0; i < availableSlots.size(); ++i) { int slot = availableSlots.get(i); // .copy() is mandatory! remainder = dest.insertItem(slot, current.copy(), action == Action.SIMULATE); // If we inserted *something* if (remainder.isEmpty() || current.getCount() != remainder.getCount()) { availableSlots.remove(i); break; } } if (remainder.isEmpty()) { // If we inserted successfully, get a next stack. current = stacks.poll(); } else if (current.getCount() == remainder.getCount()) { // If we didn't insert anything over ALL these slots, stop here. break; } else { // If we didn't insert all, continue with other slots and use our remainder. current = remainder; } } boolean success = current == null && stacks.isEmpty(); if (!success && action == Action.PERFORM) { LogManager.getLogger().warn("Inventory unexpectedly didn't accept {}, the remainder has been voided!", current != null ? current.getDescriptionId() : null); } return success; } /** * Called by Autocrafting when it uses this crafter in a processing recipe that has fluids as input * * @param toInsert Collection of Fluidstack stacklist entries to insert into the inventory * @param action action to perform * @return whether insertion was successful */ default boolean insertFluidsIntoInventory(Collection toInsert, Action action) { IFluidHandler dest = getConnectedFluidInventory(); if (toInsert.isEmpty()) { return true; } if (dest == null) { return false; } for (FluidStack stack : toInsert) { int filled = dest.fill(stack, action == Action.SIMULATE ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE); if (filled != stack.getAmount()) { if (action == Action.PERFORM) { LogManager.getLogger().warn("Inventory unexpectedly didn't accept all of {}, the remainder has been voided!", stack.getTranslationKey()); } return false; } } return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternProvider.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import javax.annotation.Nonnull; /** * Implement this interface on crafting pattern items. * When this interface is implemented on the item in question, they will be insertable in crafters. */ public interface ICraftingPatternProvider { /** * Creates a crafting pattern. * * @param level the level * @param stack the pattern stack, the implementor needs to copy it * @param container the {@link ICraftingPatternContainer} where the pattern is in * @return the crafting pattern */ @Nonnull ICraftingPattern create(Level level, ItemStack stack, ICraftingPatternContainer container); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/ICraftingPatternRenderHandler.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting; import com.refinedmods.refinedstorage.api.IRSAPI; import net.minecraft.world.item.ItemStack; /** * Defines the behavior of pattern rendering. * One can add this interface through {@link IRSAPI#addPatternRenderHandler(ICraftingPatternRenderHandler)}. */ public interface ICraftingPatternRenderHandler { /** * Returns true if the pattern can render its output. * As soon as one {@link ICraftingPatternRenderHandler} returns true for this method, it will render the output. * * @param pattern the pattern * @return true if this pattern can render its output, false otherwise */ boolean canRenderOutput(ItemStack pattern); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElement.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import java.util.Collections; import java.util.List; /** * Represents a crafting monitor element. */ public interface ICraftingMonitorElement { /** * @param graphics the graphics * @param x position on the x axis to render * @param y position on the y axis to render * @param drawers the drawers that this element can use */ @OnlyIn(Dist.CLIENT) void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers); /** * Returns the id for the base of this element, used for sorting in the {@link CraftingMonitorElementList} * * @return the id */ ResourceLocation getBaseId(); /** * Returns the id of this element, used for serialization and deserialization over the network. * * @return the id */ ResourceLocation getId(); /** * @return the tooltip of this element */ default List getTooltip() { return Collections.emptyList(); } /** * Writes the data to the network. * * @param buf the buffer */ void write(FriendlyByteBuf buf); /** * Merge an element into the current element. * * @param element the element to merged with the current one * @return true if merge was successful, false otherwise */ boolean merge(ICraftingMonitorElement element); /** * @return the hash code for the underlying base item/fluid element */ int baseElementHashCode(); /** * @return the hash code for the underlying element */ int elementHashCode(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElementList.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor; import java.util.List; public interface ICraftingMonitorElementList { /** * Directly add to the underlying list without trying to merge. * * @param element the {@link ICraftingMonitorElement} */ void directAdd(ICraftingMonitorElement element); /** * Add a element to the Storage list, similar elements will be merged. * A {@link #commit()} will stop any following adds to be merged with previous ones. * * @param element the {@link ICraftingMonitorElement} */ void addStorage(ICraftingMonitorElement element); /** * Add a element to the Processing or Crafting list, similar elements will be merged. * A {@link #commit()} will stop any following adds to be merged with previous ones. * * @param element the {@link ICraftingMonitorElement} * @param isProcessing whether to add to the processing list or the crafting list */ void add(ICraftingMonitorElement element, boolean isProcessing); /** * Add a element to the list, similar elements will be merged. * A {@link #commit()} will stop any following adds to be merged with previous ones. * * @param element the {@link ICraftingMonitorElement} */ void add(ICraftingMonitorElement element); /** * Finishes a current merge operation. */ void commit(); /** * Gets all the elements in the list. * This also commits the last changes. * * @return the current list of elements */ List getElements(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorElementRegistry.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.function.Function; /** * This registry holds factories for crafting monitor elements (for serialization and deserialization over the network). */ public interface ICraftingMonitorElementRegistry { /** * Adds a factory to the registry. * * @param id the id, as specified in {@link ICraftingMonitorElement#getId()} * @param factory the factory */ void add(ResourceLocation id, Function factory); /** * Returns a factory from the registry. * * @param id the id, as specified in {@link ICraftingMonitorElement#getId()} * @return the factory, or null if no factory was found */ @Nullable Function get(ResourceLocation id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/craftingmonitor/ICraftingMonitorListener.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; /** * Add this listener to a {@link ICraftingManager} to listen to crafting task changes. */ public interface ICraftingMonitorListener { /** * Called when this listener is attached to a {@link ICraftingManager}. */ void onAttached(); /** * Called when any task changes. */ void onChanged(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/ICraftingPreviewElement.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.preview; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; /** * Represents a crafting preview element. */ public interface ICraftingPreviewElement { /** * @param graphics the graphics * @param x position on the x axis to render * @param y position on the y axis to render * @param drawers the drawers this element can use */ @OnlyIn(Dist.CLIENT) void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers); /** * @return true when this crafting preview elements signifies an error that disables starting a task */ boolean doesDisableTaskStarting(); /** * @param buf buffer to write to */ void write(FriendlyByteBuf buf); /** * Returns the id of this element, used for serialization and deserialization over the network. * * @return the id */ ResourceLocation getId(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/preview/ICraftingPreviewElementRegistry.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.preview; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.function.Function; /** * This registry holds factories for crafting preview elements (for serialization and deserialization over the network). */ public interface ICraftingPreviewElementRegistry { /** * Adds a factory to the registry. * * @param id the id, as specified in {@link ICraftingPreviewElement#getId()} * @param factory the factory */ void add(ResourceLocation id, Function factory); /** * Returns a factory from the registry. * * @param id the id, as specified in {@link ICraftingPreviewElement#getId()} * @return the factory, or null if no factory was found */ @Nullable Function get(ResourceLocation id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/CalculationResultType.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; /** * The result type. */ public enum CalculationResultType { /** * No problems. */ OK, /** * Some requirements are missing. */ MISSING, /** * There is no pattern for the requested stack. */ NO_PATTERN, /** * When the crafting task would cause too much server strain or is too complex. */ TOO_COMPLEX, /** * When one of the used patterns during the calculation reuses itself again and would cause an infinite loop. */ RECURSIVE; } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/CraftingTaskReadException.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import com.refinedmods.refinedstorage.api.network.INetwork; /** * Gets thrown from {@link ICraftingTaskFactory#createFromNbt(INetwork, net.minecraft.nbt.CompoundNBT)}. */ public class CraftingTaskReadException extends Exception { /** * @param message the message */ public CraftingTaskReadException(String message) { super(message); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICalculationResult.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import javax.annotation.Nullable; import java.util.List; /** * The result of the crafting calculation. */ public interface ICalculationResult { /** * @return the type */ CalculationResultType getType(); /** * @return get a list of preview elements */ List getPreviewElements(); /** * @return the task if the calculation {@link #isOk()}, otherwise null */ @Nullable ICraftingTask getTask(); /** * @return whether the calculation succeeded */ boolean isOk(); /** * If this result type is a {@link CalculationResultType#RECURSIVE}, the recursed pattern will be returned here. * * @return the recursed pattern, or null if this result is not {@link CalculationResultType#RECURSIVE} */ @Nullable ICraftingPattern getRecursedPattern(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingRequestInfo.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; /** * Contains information about a crafting request. */ public interface ICraftingRequestInfo { /** * @return the item requested, or null if no item was requested */ @Nullable ItemStack getItem(); /** * @return the fluid requested, or null if no fluid was requested */ @Nullable FluidStack getFluid(); /** * @return the written tag */ CompoundTag writeToNbt(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTask.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.network.INetwork; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; import java.util.UUID; /** * Represents a crafting task. */ public interface ICraftingTask { /** * Updates this task. * * @return true if this crafting task is finished, false otherwise */ boolean update(); /** * Called when this task is cancelled. */ void onCancelled(); /** * @return the amount of items that have to be crafted */ int getQuantity(); /** * @return the completion percentage */ int getCompletionPercentage(); /** * @return the stack requested */ ICraftingRequestInfo getRequested(); /** * Called when a stack is inserted into the system through {@link INetwork#insertItemTracked(ItemStack, int)}. * * @param stack the stack * @return the remainder of this stack after processing of the task */ int onTrackedInsert(ItemStack stack, int size); /** * Called when a stack is inserted into the system through {@link INetwork#insertFluidTracked(FluidStack, int)}. * * @param stack the stack * @return the remainder of this stack after processing of the task */ int onTrackedInsert(FluidStack stack, int size); /** * Writes this task to NBT. * * @param tag the tag * @return the written tag */ CompoundTag writeToNbt(CompoundTag tag); /** * @return the elements of this task for display in the crafting monitor */ List getCraftingMonitorElements(); /** * @return the crafting pattern corresponding to this task */ ICraftingPattern getPattern(); /** * @return the unix time in ms when this task has started */ long getStartTime(); /** * @return the id of this task */ UUID getId(); /** * Start the CraftingTask */ void start(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTaskFactory.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.network.INetwork; import net.minecraft.nbt.CompoundTag; /** * A factory that creates a crafting task. * Register this factory in the {@link ICraftingTaskRegistry}. */ public interface ICraftingTaskFactory { /** * Returns a crafting task for a given pattern. * * @param network the network * @param requested the request info * @param pattern the pattern * @param quantity the quantity * @return the calculation result */ ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern); /** * Returns a crafting task for a given NBT tag. * * @param network the network * @param tag the tag * @return the crafting task */ ICraftingTask createFromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException; } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/autocrafting/task/ICraftingTaskRegistry.java ================================================ package com.refinedmods.refinedstorage.api.autocrafting.task; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; /** * A registry that stores crafting task factories. * Implement this to handle the loading of custom crafting tasks. */ public interface ICraftingTaskRegistry { /** * Adds a crafting task factory to the registry. * The id is used for identifying tasks when they are read from disk. * * @param id the id of the factory * @param factory the factory */ void add(ResourceLocation id, ICraftingTaskFactory factory); /** * Returns the crafting task factory by factory id. * * @param id the factory id * @return the factory, or null if there is no factory */ @Nullable ICraftingTaskFactory get(ResourceLocation id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetwork.java ================================================ package com.refinedmods.refinedstorage.api.network; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.security.ISecurityManager; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.energy.IEnergyStorage; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import java.util.function.Predicate; /** * Represents a network. */ public interface INetwork { /** * @return the energy usage per tick of this network */ int getEnergyUsage(); /** * @return the energy storage */ IEnergyStorage getEnergyStorage(); /** * @return the network type */ NetworkType getType(); /** * @return true if this network is able to run (usually corresponds to the redstone configuration), false otherwise */ boolean canRun(); /** * Updates the network. */ void update(); /** * Called when the network is removed. */ void onRemoved(); /** * @return a graph of connected nodes to this network */ INetworkNodeGraph getNodeGraph(); /** * @return the {@link ISecurityManager} of this network */ ISecurityManager getSecurityManager(); /** * @return the {@link ICraftingManager} of this network */ ICraftingManager getCraftingManager(); /** * @return the {@link IItemGridHandler} of this network */ IItemGridHandler getItemGridHandler(); /** * @return the {@link IFluidGridHandler} of this network */ IFluidGridHandler getFluidGridHandler(); /** * @return the {@link INetworkItemManager} of this network */ INetworkItemManager getNetworkItemManager(); /** * @return the {@link IStorageCache} of this network */ IStorageCache getItemStorageCache(); /** * @return the {@link IStorageCache} of this network */ IStorageCache getFluidStorageCache(); /** * Inserts an item in this network. * * @param stack the stack prototype to insert, can be empty, do NOT modify * @param size the amount of that prototype that has to be inserted * @param action the action * @return an empty stack if the insert was successful, or a stack with the remainder */ @Nonnull ItemStack insertItem(@Nonnull ItemStack stack, int size, Action action); /** * Inserts an item and notifies the crafting manager of the incoming item. * * @param stack the stack prototype to insert, can be empty, do NOT modify * @param size the amount of that prototype that has to be inserted * @return an empty stack if the insert was successful, or a stack with the remainder */ @Nonnull default ItemStack insertItemTracked(@Nonnull ItemStack stack, int size) { int remainder = getCraftingManager().track(stack, size); if (remainder == 0) { return ItemStack.EMPTY; } return insertItem(stack, remainder, Action.PERFORM); } /** * Extracts an item from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param flags the flags to compare on, see {@link IComparer} * @param action the action * @param filter a filter for the storage * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action, Predicate> filter); /** * Extracts an item from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param flags the flags to compare on, see {@link IComparer} * @param action the action * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull default ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action) { return extractItem(stack, size, flags, action, s -> true); } /** * Extracts an item from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param action the action * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull default ItemStack extractItem(@Nonnull ItemStack stack, int size, Action action) { return extractItem(stack, size, IComparer.COMPARE_NBT, action); } /** * Inserts a fluid in this network. * * @param stack the stack prototype to insert, do NOT modify * @param size the amount of that prototype that has to be inserted * @param action the action * @return an empty stack if the insert was successful, or a stack with the remainder */ @Nonnull FluidStack insertFluid(@Nonnull FluidStack stack, int size, Action action); /** * Inserts a fluid and notifies the crafting manager of the incoming fluid. * * @param stack the stack prototype to insert, do NOT modify * @param size the amount of that prototype that has to be inserted * @return an empty stack if the insert was successful, or a stack with the remainder */ @Nonnull default FluidStack insertFluidTracked(@Nonnull FluidStack stack, int size) { int remainder = getCraftingManager().track(stack, size); if (remainder == 0) { return FluidStack.EMPTY; } return insertFluid(stack, remainder, Action.PERFORM); } /** * Extracts a fluid from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param flags the flags to compare on, see {@link IComparer} * @param action the action * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, Action action, Predicate> filter); /** * Extracts a fluid from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param flags the flags to compare on, see {@link IComparer} * @param action the action * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull default FluidStack extractFluid(FluidStack stack, int size, int flags, Action action) { return extractFluid(stack, size, flags, action, s -> true); } /** * Extracts a fluid from this network. * * @param stack the prototype of the stack to extract, do NOT modify * @param size the amount of that prototype that has to be extracted * @param action the action * @return an empty stack if nothing was extracted, or a stack with the result */ @Nonnull default FluidStack extractFluid(FluidStack stack, int size, Action action) { return extractFluid(stack, size, IComparer.COMPARE_NBT, action); } /** * @return the storage tracker for items */ IStorageTracker getItemStorageTracker(); /** * @return the storage tracker for fluids */ IStorageTracker getFluidStorageTracker(); /** * @return the level where this network is in */ Level getLevel(); /** * @return the position of this network in the level */ BlockPos getPosition(); /** * @return a read network */ INetwork readFromNbt(CompoundTag tag); /** * @param tag the tag to write to * @return a written tag */ CompoundTag writeToNbt(CompoundTag tag); /** * @return sampled tick times */ long[] getTickTimes(); /** * Marks the network dirty. */ void markDirty(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetworkManager.java ================================================ package com.refinedmods.refinedstorage.api.network; import net.minecraft.core.BlockPos; import javax.annotation.Nullable; import java.util.Collection; /** * This is a registry for network nodes in the level. */ public interface INetworkManager { /** * Gets a network from the registry at a given position. * * @param pos the position of the network * @return the network at the given position, or null if no network was found */ @Nullable INetwork getNetwork(BlockPos pos); /** * Removes a network from the registry at a given position. * * @param pos the position of the network */ void removeNetwork(BlockPos pos); /** * Sets a network in the registry at a given position. * * @param pos the position of the network * @param node the node */ void setNetwork(BlockPos pos, INetwork node); /** * @return all networks in this registry */ Collection all(); /** * Marks the network manager for saving. */ void markForSaving(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraph.java ================================================ package com.refinedmods.refinedstorage.api.network; import com.refinedmods.refinedstorage.api.util.Action; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import java.util.Collection; import java.util.function.Consumer; /** * Represents a graph of all the nodes connected to a network. */ public interface INetworkNodeGraph { /** * Rebuilds the network graph. * * @param action whether to perform or simulate * @param level the origin level * @param origin the origin, usually the network position */ void invalidate(Action action, Level level, BlockPos origin); /** * Runs an action on the network. * If the network is rebuilding it's graph, the action will be executed after the graph was built. * * @param handler the action to run */ void runActionWhenPossible(Consumer handler); /** * @return a collection of all connected entries */ Collection all(); /** * @param listener the listener */ void addListener(INetworkNodeGraphListener listener); /** * Disconnects and notifies all connected nodes. */ void disconnectAll(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraphEntry.java ================================================ package com.refinedmods.refinedstorage.api.network; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; /** * An entry in the network graph. * Implementors MUST implement equals and hashCode. */ public interface INetworkNodeGraphEntry { INetworkNode getNode(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeGraphListener.java ================================================ package com.refinedmods.refinedstorage.api.network; /** * A listener for the node graph. */ public interface INetworkNodeGraphListener { /** * Called when the graph changes. */ void onChanged(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/INetworkNodeVisitor.java ================================================ package com.refinedmods.refinedstorage.api.network; import com.refinedmods.refinedstorage.api.util.Action; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import javax.annotation.Nullable; /** * Allows the network nodes to implement more optimal or non-regular discovery of other (neighboring) nodes. */ public interface INetworkNodeVisitor { /** * Called by the network node graph when a {@link Operator} has requested this node to be visited. * * @param operator the operator */ void visit(Operator operator); /** * An operator is passed to the {@link #visit(Operator)} method to allow the network node visitor to add positions of nodes to scan. */ interface Operator { /** * Calling this method in {@link #visit(Operator)} will make the network graph scan the given level and position. * If there is another {@link INetworkNodeVisitor} at that position, it will call that visitor. * If there is no {@link INetworkNodeVisitor} at that position, it will use a default implementation which scans neighbors. * * @param level the level * @param pos the position * @param side the side */ void apply(Level level, BlockPos pos, @Nullable Direction side); /** * Returns whether the network graph is scanning in simulation mode. * * @return the action */ Action getAction(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/IWirelessTransmitter.java ================================================ package com.refinedmods.refinedstorage.api.network; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.Level; /** * Represents a node that can send a wireless signal. */ public interface IWirelessTransmitter { /** * @return the range in blocks of this transmitter, starting from {@link IWirelessTransmitter#getOrigin()} */ int getRange(); /** * @return the position where the wireless signal starts */ BlockPos getOrigin(); /** * @return the dimension in which the transmitter is */ ResourceKey getDimension(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/NetworkType.java ================================================ package com.refinedmods.refinedstorage.api.network; /** * Represents a network type. */ public enum NetworkType { /** * A normal network. */ NORMAL, /** * A creative network. */ CREATIVE } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/GridFactoryType.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; /** * The type of grid factory. */ public enum GridFactoryType { /** * A grid factory for item stacks. */ STACK, /** * A grid factory for blocks with a position. */ BLOCK } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/GridType.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import net.minecraft.util.StringRepresentable; import javax.annotation.Nonnull; /** * Represents a grid type. * Used in {@link IGrid} to determine grid GUI rendering. */ public enum GridType implements StringRepresentable { /** * A regular grid. */ NORMAL(0, "normal"), /** * A crafting grid. */ CRAFTING(1, "crafting"), /** * A pattern grid. */ PATTERN(2, "pattern"), /** * A fluid grid. */ FLUID(3, "fluid"); private final int id; private final String name; GridType(int id, String name) { this.id = id; this.name = name; } @Nonnull @Override public String getSerializedName() { return name; } @Override public String toString() { return name; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/ICraftingGridBehavior.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.api.util.IStackList; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import javax.annotation.Nullable; /** * Defines default behavior of crafting grids. */ public interface ICraftingGridBehavior { /** * Logic for regular crafting. * * @param grid the grid * @param recipe the recipe * @param player the player * @param availableItems the items available for shift crafting * @param usedItems the items used by shift crafting */ void onCrafted(INetworkAwareGrid grid, CraftingRecipe recipe, Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems); /** * Logic for crafting with shift click (mass crafting). * * @param grid the grid * @param player the player */ void onCraftedShift(INetworkAwareGrid grid, Player player); /** * Logic for when a recipe is transferred to the grid. * * @param grid the grid * @param player the player * @param recipe the recipe */ void onRecipeTransfer(INetworkAwareGrid grid, Player player, ItemStack[][] recipe); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/ICraftingGridListener.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; /** * A crafting listener for the grid. */ public interface ICraftingGridListener { /** * Called when the crafting matrix was changed. * Usually you'd send slot updates for the crafting slots (and output slot) here, so that all clients get an actual view. * This listener exists so the crafting result slot is only calculated on the server. */ void onCraftingMatrixChanged(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGrid.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; import java.util.List; /** * Represents a grid. */ public interface IGrid { int TABS_PER_PAGE = 5; int SORTING_DIRECTION_ASCENDING = 0; int SORTING_DIRECTION_DESCENDING = 1; int SORTING_TYPE_QUANTITY = 0; int SORTING_TYPE_NAME = 1; int SORTING_TYPE_ID = 2; int SORTING_TYPE_LAST_MODIFIED = 4; int SEARCH_BOX_MODE_NORMAL = 0; int SEARCH_BOX_MODE_NORMAL_AUTOSELECTED = 1; int SEARCH_BOX_MODE_JEI_SYNCHRONIZED = 2; int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED = 3; int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY = 4; int SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED = 5; int VIEW_TYPE_NORMAL = 0; int VIEW_TYPE_NON_CRAFTABLES = 1; int VIEW_TYPE_CRAFTABLES = 2; int SIZE_STRETCH = 0; int SIZE_SMALL = 1; int SIZE_MEDIUM = 2; int SIZE_LARGE = 3; static boolean isValidViewType(int type) { return type == VIEW_TYPE_NORMAL || type == VIEW_TYPE_CRAFTABLES || type == VIEW_TYPE_NON_CRAFTABLES; } static boolean isValidSearchBoxMode(int mode) { return mode == SEARCH_BOX_MODE_NORMAL || mode == SEARCH_BOX_MODE_NORMAL_AUTOSELECTED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED; } static boolean isSearchBoxModeWithAutoselection(int mode) { return mode == SEARCH_BOX_MODE_NORMAL_AUTOSELECTED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED; } static boolean doesSearchBoxModeUseJEI(int mode) { return mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY || mode == SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED; } static boolean isValidSortingType(int type) { return type == SORTING_TYPE_QUANTITY || type == SORTING_TYPE_NAME || type == SORTING_TYPE_ID || type == SORTING_TYPE_LAST_MODIFIED; } static boolean isValidSortingDirection(int direction) { return direction == SORTING_DIRECTION_ASCENDING || direction == SORTING_DIRECTION_DESCENDING; } static boolean isValidSize(int size) { return size == SIZE_STRETCH || size == SIZE_SMALL || size == SIZE_MEDIUM || size == SIZE_LARGE; } /** * @return the grid type */ GridType getGridType(); /** * @param player the player to create a listener for * @return a listener for this grid, will be attached to the storage cache in {@link #getStorageCache()} */ IStorageCacheListener createListener(ServerPlayer player); /** * @return the storage cache for this grid, or null if this grid is unavailable */ @Nullable IStorageCache getStorageCache(); /** * @return the item grid handler, or null if there is no handler available */ @Nullable IItemGridHandler getItemHandler(); /** * @return the fluid grid handler, or null if there is no handler available */ @Nullable IFluidGridHandler getFluidHandler(); /** * @param listener the listener */ default void addCraftingListener(ICraftingGridListener listener) { } /** * @param listener the listener */ default void removeCraftingListener(ICraftingGridListener listener) { } /** * @return the title */ Component getTitle(); /** * @return the view type */ int getViewType(); /** * @return the sorting type */ int getSortingType(); /** * @return the sorting direction */ int getSortingDirection(); /** * @return the search box mode */ int getSearchBoxMode(); /** * @return the current tab that is selected */ int getTabSelected(); /** * @return the current page that the tab is on */ int getTabPage(); /** * @return the total amount of tab pages */ int getTotalTabPages(); /** * @return the size mode */ int getSize(); /** * @param type the new view type */ void onViewTypeChanged(int type); /** * @param type the new sorting type */ void onSortingTypeChanged(int type); /** * @param direction the new direction */ void onSortingDirectionChanged(int direction); /** * @param searchBoxMode the new search box mode */ void onSearchBoxModeChanged(int searchBoxMode); /** * @param size the new size mode */ void onSizeChanged(int size); /** * @param tab the new selected tab */ void onTabSelectionChanged(int tab); /** * @param page the new selected page */ void onTabPageChanged(int page); /** * @return the filters */ List getFilters(); /** * @return the tabs */ List getTabs(); /** * @return the inventory of the filters */ IItemHandlerModifiable getFilter(); /** * @return the crafting matrix, or null if not a crafting grid */ @Nullable CraftingContainer getCraftingMatrix(); /** * @return the crafting result inventory, or null if not a crafting grid */ @Nullable ResultContainer getCraftingResult(); /** * Called when the crafting matrix changes. */ void onCraftingMatrixChanged(); /** * Called when an item is crafted in a crafting grid. * * @param player the player that crafted the item * @param availableItems the items available for shift crafting * @param usedItems the items used by shift crafting */ void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems); /** * Called when the clear button is pressed in the pattern grid or crafting grid. */ void onClear(Player player); /** * Called when an item is crafted with shift click (up to 64 items) in a crafting grid. * * @param player the player that crafted the item */ void onCraftedShift(Player player); /** * Called when a JEI recipe transfer occurs. * * @param player the player * @param recipe a 9*x array stack array, where x is the possible combinations for the given slot */ void onRecipeTransfer(Player player, ItemStack[][] recipe); /** * Called when the grid is closed. * * @param player the player */ void onClosed(Player player); /** * @return true if the grid is active, false otherwise */ boolean isGridActive(); /** * @return the slot id where this grid is located, if applicable, otherwise -1 */ int getSlotId(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridFactory.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; /** * Creates a grid. */ public interface IGridFactory { /** * Creates a grid from a stack. Used when {@link #getType()} is STACK. * * @param player the player * @param stack the stack * @param slot the slot in the players inventory or curio slot, otherwise -1 * @return the grid, or null if a problem occurred */ @Nullable IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot); /** * Creates a grid from a block. Used when {@link #getType()} is BLOCK. * * @param player the player * @param pos the block position * @return the grid, or null if a problem occurred */ @Nullable IGrid createFromBlock(Player player, BlockPos pos); /** * Returns a possible block entity for this grid if {@link #getType()} is BLOCK. * * @param level the level * @param pos the position * @return the block entity, or null if no block entity is required */ @Nullable BlockEntity getRelevantBlockEntity(Level level, BlockPos pos); /** * @return the type */ GridFactoryType getType(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridManager.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; /** * Manages {@link IGridFactory} instances and has code that opens grids. */ public interface IGridManager { /** * @param id the id of this factory * @param factory the factory */ void add(ResourceLocation id, IGridFactory factory); /** * Opens a grid. Can only be called on the server. * * @param id the grid factory id * @param player the player * @param pos the block position */ void openGrid(ResourceLocation id, ServerPlayer player, BlockPos pos); /** * Opens a grid. Can only be called on the server. * * @param id the grid factory id * @param player the player * @param stack the stack * @param slot the slot in the players inventory or curio slot, otherwise -1 */ void openGrid(ResourceLocation id, ServerPlayer player, ItemStack stack, PlayerSlot slot); /** * Creates a grid. * * @param id the grid factory id * @param player the player * @param stack the stack, if there is one * @param pos the block position, if there is one * @param slot the slot in the players inventory,or curio slot, otherwise -1 * @return a grid, or null if an error has occurred */ @Nullable Pair createGrid(ResourceLocation id, Player player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/IGridTab.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.api.util.IFilter; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; /** * Represents a grid tab. */ public interface IGridTab { int TAB_WIDTH = 28; int TAB_HEIGHT = 31; /** * @return the filters */ List getFilters(); /** * Draws the tooltip of this tab at the given position. * * @param font the font * @param graphics the graphics * @param x the x position * @param y the y position */ void drawTooltip(Font font, GuiGraphics graphics, int x, int y); /** * Draws the icon. * * @param graphics the graphics * @param x the x position * @param y the y position */ void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/INetworkAwareGrid.java ================================================ package com.refinedmods.refinedstorage.api.network.grid; import com.refinedmods.refinedstorage.api.network.INetwork; import javax.annotation.Nullable; /** * A grid that knows about a network. */ public interface INetworkAwareGrid extends IGrid { /** * @return the network, or null if no network is available */ @Nullable INetwork getNetwork(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/handler/IFluidGridHandler.java ================================================ package com.refinedmods.refinedstorage.api.network.grid.handler; import com.refinedmods.refinedstorage.api.util.StackListEntry; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; import java.util.UUID; /** * Defines the behavior of fluid grids. */ public interface IFluidGridHandler { /** * Called when a player tries to extract a fluid from the grid. * * @param player the player that is attempting the extraction * @param id the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry} * @param shift true if shift click was used, false otherwise */ void onExtract(ServerPlayer player, UUID id, boolean shift); /** * Called when a player tries to insert fluids in the grid. * * @param player the player * @param container a stack with a fluid container we're trying to insert * @return the remainder, or an empty stack if there is no remainder */ @Nonnull ItemStack onInsert(ServerPlayer player, ItemStack container); /** * Called when a player is trying to insert a fluid that it is holding in their hand in the GUI. * * @param player the player that is attempting the insert */ void onInsertHeldContainer(ServerPlayer player); /** * Called when a player requests the crafting preview window to be opened. * * @param player the player * @param id the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry} * @param quantity the amount of that item that we need a preview for * @param noPreview true if the crafting preview window shouldn't be shown, false otherwise */ void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview); /** * Called when a player requested crafting for an item. * * @param player the player that is requesting the crafting * @param id the id of the fluid we're trying to extract, this id is the id from {@link StackListEntry} * @param quantity the amount of the item that has to be crafted */ void onCraftingRequested(ServerPlayer player, UUID id, int quantity); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/grid/handler/IItemGridHandler.java ================================================ package com.refinedmods.refinedstorage.api.network.grid.handler; import com.refinedmods.refinedstorage.api.util.StackListEntry; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.UUID; /** * Defines the behavior of item grids. */ public interface IItemGridHandler { int EXTRACT_HALF = 1; int EXTRACT_SINGLE = 2; int EXTRACT_SHIFT = 4; /** * Called when a player tries to extract an item from the grid through the Inventory * * @param player the player that is attempting the extraction * @param stack the stack we're trying to extract * @param preferredSlot playerInventory slot to prefer when adding or -1 * @param flags how we are extracting, see the flags in {@link IItemGridHandler} */ void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags); /** * Called when a player tries to extract an item from the grid. * * @param player the player that is attempting the extraction * @param id the id of the item we're trying to extract, this id is the id from {@link StackListEntry} * @param preferredSlot playerInventory slot to prefer when adding or -1 * @param flags how we are extracting, see the flags in {@link IItemGridHandler} */ void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags); /** * Called when a player tries to insert an item in the grid. * * @param player the player that is attempting the insert * @param stack the item we're trying to insert * @param single true if we are only inserting a single item, false otherwise * @return the remainder, or an empty stack if there is no remainder */ @Nonnull ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single); /** * Called when a player is trying to insert an item that it is holding in their hand in the GUI. * * @param player the player that is attempting the insert * @param single true if we are only inserting a single item, false otherwise */ void onInsertHeldItem(ServerPlayer player, boolean single); /** * Called when a player requests the crafting preview window to be opened. * * @param player the player * @param id the id of the item we're trying to extract, this id is the id from {@link StackListEntry} * @param quantity the amount of that item that we need a preview for * @param noPreview true if the crafting preview window shouldn't be shown, false otherwise */ void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview); /** * Called when a player requested crafting for an item. * * @param player the player that is requesting the crafting * @param id the id of the item we're trying to extract, this id is the id from {@link StackListEntry} * @param quantity the amount of the item that has to be crafted */ void onCraftingRequested(ServerPlayer player, UUID id, int quantity); /** * Called when a player wants to cancel a crafting task. * * @param player the player that requested the cancel * @param id the task id, or null to cancel all tasks that are in the network currently */ void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id); /** * Called when a player shift or ctrl scrolls in the player inventory * * @param player player that is scrolling * @param slot slot the mouse is hovering over * @param shift if true shift is pressed, if false ctrl is pressed * @param up whether the player is scrolling up or down */ void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up); /** * Called when a player shift or ctrl scrolls in the Grid View * * @param player player that is scrolling * @param id UUID of the GridStack that the mouse is hovering over or null * @param shift if true shift is pressed, if false ctrl is pressed * @param up whether the player is scrolling up or down */ void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItem.java ================================================ package com.refinedmods.refinedstorage.api.network.item; import com.refinedmods.refinedstorage.api.network.INetwork; import net.minecraft.world.entity.player.Player; /** * Represents a network item (an item that is connected to the network somehow). * You do not implement this on the item itself, use an {@link INetworkItemProvider} for that. * This is an object used separately from the actual item, since this stores the player that is using it. */ public interface INetworkItem { /** * @return the player using the network item */ Player getPlayer(); /** * Called when the network item is being opened. * * @param network the network * @return true if the item can be opened, false otherwise */ boolean onOpen(INetwork network); /** * @param energy the energy to extract */ void drainEnergy(int energy); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItemManager.java ================================================ package com.refinedmods.refinedstorage.api.network.item; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; /** * This is the handler for network items of a network. * It stores which player is currently using what network item. */ public interface INetworkItemManager { /** * Called when a player opens a network item. * * @param player the player that opened the network item * @param stack the stack that has been opened * @param slot the slot in the players inventory or curio slot, otherwise -1 */ void open(Player player, ItemStack stack, PlayerSlot slot); /** * Called when the player closes a network item. * * @param player the player that closed the network item */ void close(Player player); /** * Returns a {@link INetworkItem} for a player. * * @param player the player to get the network item for * @return the {@link INetworkItem} that corresponds to a player, or null if the player isn't using a network item */ @Nullable INetworkItem getItem(Player player); /** * @param player the player * @param energy energy to extract */ void drainEnergy(Player player, int energy); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/item/INetworkItemProvider.java ================================================ package com.refinedmods.refinedstorage.api.network.item; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; /** * Provider for network items, implement this on the item. */ public interface INetworkItemProvider { /** * Creates a network item for the given item stack. * * @param handler the network item handler * @param player the player * @param stack the stack * @param slot the slot in the players inventory or curio slot, otherwise -1 * @return the network item */ @Nonnull INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/ICoverable.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; public interface ICoverable { CoverManager getCoverManager(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNode.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import com.refinedmods.refinedstorage.api.network.INetwork; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.UUID; /** * Represents a node in the network. */ public interface INetworkNode { /** * @return the energy usage of this node */ int getEnergyUsage(); /** * Returns the stack that is displayed in the controller GUI. * Can be an empty stack if no stack should be shown. * * @return the item stack of this node */ @Nonnull ItemStack getItemStack(); /** * Called when this node is connected to a network. * * @param network the network */ void onConnected(INetwork network); /** * Called when this node is disconnected from a network. * This happens when the node is removed, or if the network is removed. * 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. * * @param network the network */ void onDisconnected(INetwork network); /** * Whether this node is active, independent of the network. * * @return true if this node is active, false otherwise */ boolean isActive(); /** * @return the network, or null if this node is not connected to any network */ @Nullable INetwork getNetwork(); /** * Updates a network node. */ void update(); /** * Writes the network node data to NBT. * * @param tag the tag * @return the written tag */ CompoundTag write(CompoundTag tag); /** * @return the position of this network node */ BlockPos getPos(); /** * @return the level of this network node */ Level getLevel(); /** * Marks this node as dirty for saving. */ void markDirty(); /** * @return the id of this node as specified in {@link INetworkNodeRegistry} */ ResourceLocation getId(); /** * @param direction the direction * @return whether a network signal can be conducted in the given direction. */ default boolean canConduct(Direction direction) { return true; } /** * @param direction the direction * @return whether the network node can receiver network connections from this side */ default boolean canReceive(Direction direction) { return canConduct(direction); } /** * @return the owner */ @Nullable UUID getOwner(); /** * @param owner the owner */ void setOwner(@Nullable UUID owner); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeFactory.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.level.Level; import javax.annotation.Nonnull; /** * A factory for reading network nodes from the disk. Used in a {@link INetworkNodeRegistry}. */ public interface INetworkNodeFactory { /** * Creates a network node. * * @param tag the tag on disk * @param level the level * @param pos the pos * @return the network node */ @Nonnull INetworkNode create(CompoundTag tag, Level level, BlockPos pos); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeManager.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import net.minecraft.core.BlockPos; import javax.annotation.Nullable; import java.util.Collection; /** * This is a registry for network nodes in the level. */ public interface INetworkNodeManager { /** * Gets a network node from the registry at a given position. * * @param pos the position of the node * @return the network node at the given position, or null if no network node was found */ @Nullable INetworkNode getNode(BlockPos pos); /** * Removes a node from the registry at a given position. * * @param pos the position of the node */ void removeNode(BlockPos pos); /** * Sets a node in the registry at a given position. * * @param pos the position of the node * @param node the node */ void setNode(BlockPos pos, INetworkNode node); /** * @return all nodes in this registry */ Collection all(); /** * Marks the network node manager for saving. */ void markForSaving(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeProxy.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import javax.annotation.Nonnull; /** * Makes a network node accessible from a tile entity. Implement this as a capability. * * @param the network node */ public interface INetworkNodeProxy { /** * Returns the node. * Needs to work on the client and the server. * 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. * * @return the node */ @Nonnull T getNode(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/node/INetworkNodeRegistry.java ================================================ package com.refinedmods.refinedstorage.api.network.node; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; /** * This registry holds factories for reading and writing network nodes from and to NBT. */ public interface INetworkNodeRegistry { /** * Adds a factory to the registry. * * @param id the id, as specified in {@link INetworkNode#getId()} * @param factory the factory */ void add(ResourceLocation id, INetworkNodeFactory factory); /** * Returns a factory from the registry. * * @param id the id, as specified in {@link INetworkNode#getId()} * @return the factory, or null if no factory was found */ @Nullable INetworkNodeFactory get(ResourceLocation id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityCard.java ================================================ package com.refinedmods.refinedstorage.api.network.security; import javax.annotation.Nullable; import java.util.UUID; /** * Represents a security card. */ public interface ISecurityCard { /** * @return the owner of this card, or null if this is a global card */ @Nullable UUID getOwner(); /** * @param permission the permission to check for * @return true if the bound player has the given permission, false otherwise */ boolean hasPermission(Permission permission); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityCardContainer.java ================================================ package com.refinedmods.refinedstorage.api.network.security; import javax.annotation.Nullable; import java.util.List; /** * Represents a network node that contains security cards. */ public interface ISecurityCardContainer { /** * @return the security cards in this container, {@link ISecurityCard#getOwner()} CANNOT be null for any card in this list! */ List getCards(); /** * @return the global security card in this container, or null if there is none, {@link ISecurityCard#getOwner()}) can be null! */ @Nullable ISecurityCard getGlobalCard(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/security/ISecurityManager.java ================================================ package com.refinedmods.refinedstorage.api.network.security; import net.minecraft.world.entity.player.Player; /** * The security manager of a network. */ public interface ISecurityManager { /** * @param permission the permission to check for * @param player the player to check that permission for * @return true if the player has the given permission, false otherwise */ boolean hasPermission(Permission permission, Player player); /** * Invalidates the security list. */ void invalidate(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/network/security/Permission.java ================================================ package com.refinedmods.refinedstorage.api.network.security; /** * The various permissions a player can have in a network. */ public enum Permission { /** * Whether the player can insert items in a network. */ INSERT(0), /** * Whether the player can extract items from a network. */ EXTRACT(1), /** * Whether the player can start, cancel or view an autocrafting task. */ AUTOCRAFTING(2), /** * Whether the player can open network GUIs. */ MODIFY(3), /** * Whether the player can add or remove network blocks. */ BUILD(4), /** * Whether the player can manage the security options for a network. */ SECURITY(5); private final int id; Permission(int id) { this.id = id; } public int getId() { return id; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/render/IElementDrawer.java ================================================ package com.refinedmods.refinedstorage.api.render; import net.minecraft.client.gui.GuiGraphics; /** * This {@link FunctionalInterface} is used to define a draw/render function. * This function use x and y coords and the element to draw. * * @param the element to draw, usually {@link String}, {@link net.minecraft.world.item.ItemStack} or {@link net.neoforged.neoforge.fluids.FluidStack} */ @FunctionalInterface public interface IElementDrawer { /** * @param graphics the graphics * @param x the x axis * @param y the y axis * @param element the element type */ void draw(GuiGraphics graphics, int x, int y, T element); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/render/IElementDrawers.java ================================================ package com.refinedmods.refinedstorage.api.render; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; /** * Interface specifying default element drawers. */ public interface IElementDrawers { /** * @return an item drawer */ default IElementDrawer getItemDrawer() { return getNullDrawer(); } /** * @return a fluid drawer */ default IElementDrawer getFluidDrawer() { return getNullDrawer(); } /** * @return a string drawer */ default IElementDrawer getStringDrawer() { return getNullDrawer(); } /** * @return an overlay drawer */ default IElementDrawer getOverlayDrawer() { return getNullDrawer(); } default IElementDrawer getErrorDrawer() { return getNullDrawer(); } /** * DO NOT OVERRIDE! * * @param any type of drawer * @return a drawer that does nothing */ default IElementDrawer getNullDrawer() { return (poseStack, x, y, element) -> { // NO OP }; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/AccessType.java ================================================ package com.refinedmods.refinedstorage.api.storage; /** * The access type of a storage. */ public enum AccessType { /** * Insert and extract ability. */ INSERT_EXTRACT(0), /** * Only insert ability. */ INSERT(1), /** * Only extract ability. */ EXTRACT(2); private final int id; /** * @param id the id of this access type */ AccessType(int id) { this.id = id; } /** * @return the id of this access type */ public int getId() { return id; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/IStorage.java ================================================ package com.refinedmods.refinedstorage.api.storage; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.Comparator; public interface IStorage { Comparator> COMPARATOR = (left, right) -> { int compare = Integer.compare(right.getPriority(), left.getPriority()); return compare != 0 ? compare : Integer.compare(right.getStored(), left.getStored()); }; /** * Returns the stacks of the storage. * Empty stacks are allowed. * Please do not copy the stacks for performance reasons. * For the caller: modifying stacks is not allowed! * * @return stacks stored in this storage, empty stacks are allowed */ Collection getStacks(); /** * Inserts a stack to this storage. * * @param stack the stack prototype to insert, can be empty, do NOT modify * @param size the amount of that prototype that has to be inserted * @param action the action * @return an empty stack if the insert was successful, or a stack with the remainder */ @Nonnull T insert(@Nonnull T stack, int size, Action action); /** * Extracts a stack from this storage. *

* If the stack we found in the system is smaller than the requested size, return that stack anyway. * * @param stack a prototype of the stack to extract, can be empty, do NOT modify * @param size the amount of that prototype that has to be extracted * @param flags the flags to compare on, see {@link IComparer} * @param action the action * @return an empty stack if nothing was extracted, or an extracted stack */ @Nonnull T extract(@Nonnull T stack, int size, int flags, Action action); /** * @return the amount stored in this storage */ int getStored(); /** * @return the priority of this storage */ int getPriority(); /** * @return the access type of this storage */ AccessType getAccessType(); /** * Returns the delta that needs to be added to the item or fluid storage cache AFTER insertion of the stack. * * @param storedPreInsertion the amount stored pre insertion * @param size the size of the stack being inserted * @param remainder the remainder that we got back, or null if no remainder was there * @return the amount to increase the cache with */ int getCacheDelta(int storedPreInsertion, int size, @Nullable T remainder); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/IStorageProvider.java ================================================ package com.refinedmods.refinedstorage.api.storage; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; /** * Represents a node that provides the network with storage. */ public interface IStorageProvider { /** * @param storages the item storages */ void addItemStorages(List> storages); /** * @param storages the fluid storages */ void addFluidStorages(List> storages); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/StorageType.java ================================================ package com.refinedmods.refinedstorage.api.storage; /** * The storage type. */ public enum StorageType { ITEM, FLUID } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/cache/IStorageCache.java ================================================ package com.refinedmods.refinedstorage.api.storage.cache; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import javax.annotation.Nonnull; import java.util.List; /** * This holds all stacks from all the connected storages from a {@link INetwork}. *

* Refined Storage uses this class mainly for use in Grids and Detectors to avoid querying * individual {@link IStorage}s constantly (performance impact) and to send and detect storage changes * more efficiently. */ public interface IStorageCache { /** * Invalidates the cache. * Will also call {@link IStorageCache#sort()} to sort the storages correctly. * Typically called when a {@link IStorageProvider} is added or removed from the network. * * @param cause the cause of the invalidate */ void invalidate(InvalidateCause cause); /** * Adds a stack to the cache. *

* Note that this doesn't modify any of the connected storages, but just modifies the cache. * Use {@link IStorage#insert(Object, int, Action)} to add a stack to an actual storage. *

* Will merge it with another stack if it already exists. * * @param stack the stack to add, do NOT modify * @param size the size to add * @param rebuilding true if this method is called while rebuilding, false otherwise * @param batched true if this change needs to be batched */ void add(@Nonnull T stack, int size, boolean rebuilding, boolean batched); /** * Removes a stack from the cache. *

* Note that this doesn't modify any of the connected storages, but just modifies the cache. * Use {@link IStorage#extract(Object, int, int, Action)} to remove a stack from an actual storage. * * @param stack the stack to remove, do NOT modify * @param size the size to remove * @param batched true if this change needs to be batched, false otherwise */ void remove(@Nonnull T stack, int size, boolean batched); /** * Notifies storage cache listeners about batched up storage cache changes. */ void flush(); /** * Adds a listener to be called when this storage cache changes. * * @param listener the listener */ void addListener(IStorageCacheListener listener); /** * Removes a listener from the storage cache. * * @param listener the listener */ void removeListener(IStorageCacheListener listener); /** * Re-attaches all listeners. * In practice this means that all listeners will get a {@link IStorageCacheListener#onAttached()} call. */ void reAttachListeners(); /** * Resorts the storages in this cache according to their priority. * This needs to be called when the priority of a storage changes. */ void sort(); /** * @return the list behind this cache */ IStackList getList(); /** * @return a list of craftables */ IStackList getCraftablesList(); /** * @return grid stacks to sync initially */ List getGridStacks(); /** * @return the storages connected to this network */ List> getStorages(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/cache/IStorageCacheListener.java ================================================ package com.refinedmods.refinedstorage.api.storage.cache; import com.refinedmods.refinedstorage.api.util.StackListResult; import java.util.List; /** * Listens for storage cache changes. * * @param the type */ public interface IStorageCacheListener { /** * Called when this storage cache listener is attached to a storage cache. */ void onAttached(); /** * Called when the cache invalidates. */ void onInvalidated(); /** * Called when the storage cache changes. * * @param delta the delta */ void onChanged(StackListResult delta); /** * Called when the storage cache changes. * * @param deltas a list of deltas */ void onChangedBulk(List> deltas); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/cache/InvalidateCause.java ================================================ package com.refinedmods.refinedstorage.api.storage.cache; public enum InvalidateCause { UNKNOWN, DISK_INVENTORY_CHANGED, CONNECTED_STATE_CHANGED, DEVICE_CONFIGURATION_CHANGED, INITIAL_TICK_INVALIDATION, NEIGHBOR_CHANGED } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDisk.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import com.refinedmods.refinedstorage.api.storage.IStorage; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.UUID; /** * Represents a storage disk. * * @param the storage */ public interface IStorageDisk extends IStorage { /** * @return the capacity of this storage disk */ int getCapacity(); /** * @return the id of the owner, or null if not present */ @Nullable UUID getOwner(); /** * When this storage disk is inserted into a storage disk container, it has to adjust to the container's settings * and use the following parameters instead. * * @param listener the listener to be called when the storage changes, or null for no listener * @param context the container context, containing some settings */ void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context); /** * Writes the storage to NBT. */ CompoundTag writeToNbt(); /** * @return the factory id as registered in {@link IStorageDiskRegistry} */ ResourceLocation getFactoryId(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskContainerContext.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import com.refinedmods.refinedstorage.api.storage.AccessType; /** * Stores relevant information about the container where the {@link IStorageDisk} is in. */ public interface IStorageDiskContainerContext { /** * @return the access type */ AccessType getAccessType(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskFactory.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; import java.util.UUID; /** * Creates a storage disk from NBT or on-demand. * * @param */ public interface IStorageDiskFactory { /** * Creates a storage disk based on NBT. * * @param level the level * @param tag the tag * @return the storage disk */ IStorageDisk createFromNbt(ServerLevel level, CompoundTag tag); /** * Creates a storage disk item based on ID. * * @param disk the disk * @param id the disk id * @return the storage disk */ ItemStack createDiskItem(IStorageDisk disk, UUID id); /** * Creates a storage disk on-demand. * * @param level the level * @param capacity the capacity * @param owner the owner, or null if no owner * @return the storage disk */ IStorageDisk create(ServerLevel level, int capacity, @Nullable UUID owner); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskListener.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; /** * Listens to storage disk changes. */ public interface IStorageDiskListener { /** * Called when any change happens. */ void onChanged(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskManager.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; import java.util.Map; import java.util.UUID; /** * Stores storage disks. */ public interface IStorageDiskManager { /** * Gets a storage disk by id. * * @param id the id * @return the storage disk, or null if no storage disk is found */ @Nullable IStorageDisk get(UUID id); /** * Gets a storage disk by disk stack (a {@link IStorageDiskProvider}). * * @param disk the disk stack * @return the storage disk, or null if no storage disk is found */ @Nullable IStorageDisk getByStack(ItemStack disk); /** * @return a map of all storage disks */ Map getAll(); /** * Sets a storage disk. * * @param id the id * @param disk the disk */ void set(UUID id, IStorageDisk disk); /** * Removes a storage disk. * * @param id the id */ void remove(UUID id); /** * Marks this manager for saving. */ void markForSaving(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskProvider.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import com.refinedmods.refinedstorage.api.storage.StorageType; import net.minecraft.world.item.ItemStack; import java.util.UUID; /** * Maps disk items to an id. * Implement this on a disk item. */ public interface IStorageDiskProvider { /** * @param disk the disk * @return the id of the disk */ UUID getId(ItemStack disk); /** * @param disk the disk * @param id the id to set */ void setId(ItemStack disk, UUID id); /** * @param disk the disk * @return true if the given disk has an id set, false otherwise */ boolean isValid(ItemStack disk); /** * @param disk the disk * @return the capacity of the given disk */ int getCapacity(ItemStack disk); /** * @return the storage type */ StorageType getType(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskRegistry.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; /** * Stores factories for reproducing storage disks from disk. */ public interface IStorageDiskRegistry { /** * Adds a factory. * * @param id the id of this factory * @param factory the factory */ void add(ResourceLocation id, IStorageDiskFactory factory); /** * Gets a factory. * * @param id the factory id * @return the factory, or null if no factory was found */ @Nullable IStorageDiskFactory get(ResourceLocation id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/IStorageDiskSync.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; import javax.annotation.Nullable; import java.util.UUID; /** * Used to send requests to the server to get storage disk information ({@link StorageDiskSyncData}). */ public interface IStorageDiskSync { /** * Gets disk data by disk id. * Can return null if there is no response yet. * * @param id the disk id * @return the disk data, or null if there was no response from the server yet */ @Nullable StorageDiskSyncData getData(UUID id); /** * Sends a request to the server to get information from a storage disk. * Can be called in a loop or in high frequency, the request is throttled. * * @param id the disk id */ void sendRequest(UUID id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/disk/StorageDiskSyncData.java ================================================ package com.refinedmods.refinedstorage.api.storage.disk; /** * Contains synced info about a storage disk. */ public class StorageDiskSyncData { private final int stored; private final int capacity; public StorageDiskSyncData(int stored, int capacity) { this.stored = stored; this.capacity = capacity; } /** * @return the amount stored */ public int getStored() { return stored; } /** * @return the capacity */ public int getCapacity() { return capacity; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorage.java ================================================ package com.refinedmods.refinedstorage.api.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; /** * An external storage handler. * * @param */ public interface IExternalStorage extends IStorage { /** * For storage disks and blocks, the network detects changes and updates the {@link IStorageCache} accordingly. * However, for blocks connected to an external storage the external storage itself is responsible for bookkeeping the changes * and submitting them to the {@link IStorageCache}. That bookkeeping is supposed to happen in this method. *

* It's called every external storage tick. * * @param network the network */ void update(INetwork network); /** * @return the capacity of the connected storage */ long getCapacity(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorageContext.java ================================================ package com.refinedmods.refinedstorage.api.storage.externalstorage; import com.refinedmods.refinedstorage.api.storage.AccessType; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; /** * Provides information about an external storage. */ public interface IExternalStorageContext { /** * @return the priority of the external storage */ int getPriority(); /** * @return the access type of the external storage */ AccessType getAccessType(); /** * @param stack the stack to test * @return true if the external storage accepts the item, false otherwise */ boolean acceptsItem(ItemStack stack); /** * @param stack the stack to test * @return true if the external storage accepts the fluid, false otherwise */ boolean acceptsFluid(FluidStack stack); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/externalstorage/IExternalStorageProvider.java ================================================ package com.refinedmods.refinedstorage.api.storage.externalstorage; import javax.annotation.Nonnull; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; /** * Provides an external storage handler to the external storage block. * * @param */ public interface IExternalStorageProvider { /** * @param level the level * @param pos the position * @return true if the provider can provide, false otherwise */ boolean canProvide(Level level, BlockPos pos, Direction direction); /** * @param context the context of the external storage * @param blockEntity the block entity * @param direction the direction of the external storage * @return the external storage handler */ @Nonnull IExternalStorage provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction); /** * Returns the priority of this external storage provider. * The one with the highest priority is chosen. * Refined Storage's default handlers for {@link net.neoforged.neoforge.items.IItemHandler} and {@link net.neoforged.neoforge.fluids.capability.IFluidHandler} return 0. * This value can't be dynamic (only fixed), since the sorted order is cached. * * @return the priority */ int getPriority(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/IStorageTracker.java ================================================ package com.refinedmods.refinedstorage.api.storage.tracker; import net.minecraft.nbt.ListTag; import net.minecraft.world.entity.player.Player; import javax.annotation.Nullable; /** * Keeps track of when a stack is changed in the system. */ public interface IStorageTracker { /** * Updates the storage tracker entry for a stack, changing it's player name and modification time. * * @param player player * @param stack the stack */ void changed(Player player, T stack); /** * @param stack the stack * @return the entry, or null if the stack hasn't been modified yet */ @Nullable StorageTrackerEntry get(T stack); /** * initialize tracker from nbt * * @param nbt to read from */ void readFromNbt(ListTag nbt); /** * write data to nbt * * @return data as nbt */ ListTag serializeNbt(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/IStorageTrackerManager.java ================================================ package com.refinedmods.refinedstorage.api.storage.tracker; import com.refinedmods.refinedstorage.api.storage.StorageType; import java.util.UUID; public interface IStorageTrackerManager { /** * Marks this manager for saving. */ void markForSaving(); /** * get a storage tracker or create a new Storage Tracker if it doesn't exist * * @param itemStorageTrackerId UUID for that tracker * @param type Storage type of that tracker * @return StorageTracker */ IStorageTracker getOrCreate(UUID itemStorageTrackerId, StorageType type); /** * @param id of the Storage tracker that will be removed */ void remove(UUID id); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/storage/tracker/StorageTrackerEntry.java ================================================ package com.refinedmods.refinedstorage.api.storage.tracker; /** * Represents a storage tracker entry. */ public class StorageTrackerEntry { private final long time; private final String name; public StorageTrackerEntry(long time, String name) { this.time = time; this.name = name; } /** * @return the modification time */ public long getTime() { return time; } /** * @return the name of the player who modified this item */ public String getName() { return name; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/Action.java ================================================ package com.refinedmods.refinedstorage.api.util; /** * Defines how an action is performed. */ public enum Action { /** * Performs the action. */ PERFORM, /** * Gives back the same return as called with PERFORM, but doesn't mutate the underlying structure. */ SIMULATE } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/IComparer.java ================================================ package com.refinedmods.refinedstorage.api.util; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; /** * Utilities for comparing item and fluid stacks. */ public interface IComparer { int COMPARE_NBT = 1; int COMPARE_QUANTITY = 2; /** * Compares two stacks by the given flags. * * @param left the left stack * @param right the right stack * @param flags the flags to compare with * @return true if the left and right stack are the same, false otherwise */ boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right, int flags); /** * Compares two stacks by NBT, damage and quantity. * * @param left the left stack * @param right the right stack * @return true if the left and right stack are the same, false otherwise */ default boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right) { return isEqual(left, right, COMPARE_NBT | COMPARE_QUANTITY); } /** * Compares two stacks by NBT and damage. * * @param left the left stack * @param right the right stack * @return true if the left and right stack are the same, false otherwise */ default boolean isEqualNoQuantity(@Nonnull ItemStack left, @Nonnull ItemStack right) { return isEqual(left, right, COMPARE_NBT); } /** * Compares two stacks by the given flags. * * @param left the left stack * @param right the right stack * @param flags the flags to compare with * @return true if the left and right stack are the same, false otherwise */ boolean isEqual(@Nonnull FluidStack left, @Nonnull FluidStack right, int flags); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/IFilter.java ================================================ package com.refinedmods.refinedstorage.api.util; /** * A filter. */ public interface IFilter { int MODE_WHITELIST = 0; int MODE_BLACKLIST = 1; /** * @return the stack being filtered */ Object getStack(); /** * @return the compare flags, see {@link IComparer} */ int getCompare(); /** * @return the mode, whitelist or blacklist */ int getMode(); /** * @return true if this is a mod filter, false otherwise */ boolean isModFilter(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/IQuantityFormatter.java ================================================ package com.refinedmods.refinedstorage.api.util; /** * Utilities for formatting quantities. */ public interface IQuantityFormatter { /** * Formats a quantity as they are formatted in the Grid. * Formatted as following: "####0.#". *

* 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. * 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. * * @param qty the quantity * @return the formatted quantity */ String formatWithUnits(int qty); /** * Formats a quantity as they are formatted in the Grid. * Formatted as following: "####0.#". *

* 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. * 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. * * @param qty the quantity * @return the formatted quantity */ String formatWithUnits(long qty); /** * Formats a quantity as they are formatted on the disk tooltips. * Formatted as following: "#,###". * * @param qty the quantity * @return the formatted quantity */ String format(int qty); /** * Formats a quantity as they are formatted on the disk tooltips. * Formatted as following: "#,###". * * @param qty the quantity * @return the formatted quantity */ String format(long qty); /** * Divides quantity by 1000 and appends "B". * * @param qty the quantity * @return the formatted quantity */ String formatInBucketForm(int qty); /** * Used in Fluid Grid. * * @param qty the quantity * @return the formatted quantity */ String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/IStackList.java ================================================ package com.refinedmods.refinedstorage.api.util; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; /** * A stack list. */ public interface IStackList { /** * Adds a stack to the list, will merge it with another stack if it already exists in the list. * * @param stack the stack * @param size the size to add * @return the result */ StackListResult add(@Nonnull T stack, int size); /** * Adds a stack to the list, will merge it with another stack if it already exists in the list. * * @param stack the stack * @return the result */ StackListResult add(@Nonnull T stack); /** * Decrements the count of that stack in the list. * * @param stack the stack * @param size the size to remove * @return the result, or null if the stack wasn't present */ @Nullable StackListResult remove(@Nonnull T stack, int size); /** * Decrements the count of that stack in the list. * * @param stack the stack * @return the result, or null if the stack wasn't present */ @Nullable StackListResult remove(@Nonnull T stack); /** * Returns a stack. * * @param stack the stack to search for * @return the stack, or null if no stack was found */ @Nullable default T get(@Nonnull T stack) { return get(stack, IComparer.COMPARE_NBT); } /** * Returns the amount in this list, based on the stack and the flags. * * @param stack the stack * @param flags the flags * @return the count, 0 if not found */ int getCount(@Nonnull T stack, int flags); /** * @param stack the stack * @return the count, 0 if not found */ default int getCount(@Nonnull T stack) { return getCount(stack, IComparer.COMPARE_NBT); } /** * Returns a stack. * * @param stack the stack to search for * @param flags the flags to compare on, see {@link IComparer} * @return the stack, or null if no stack was found */ @Nullable T get(@Nonnull T stack, int flags); /** * Returns a stack entry. * * @param stack the stack to search for * @param flags the flags to compare on, see {@link IComparer} * @return the stack entry, or null if no stack entry was found */ @Nullable StackListEntry getEntry(@Nonnull T stack, int flags); /** * Returns a stack. * * @param id the id of the entry to search for * @return the stack, or null if no stack was found */ @Nullable T get(UUID id); /** * Clears the list. */ void clear(); /** * @return true if the list is empty, false otherwise */ boolean isEmpty(); /** * @return a collection of stacks in this list */ @Nonnull Collection> getStacks(); /** * @return a collection of stacks matching the given type (ignoring NBT) */ @Nonnull Collection> getStacks(@Nonnull T stack); /** * @return a new copy of this list, with the stacks in it copied as well */ @Nonnull IStackList copy(); /** * @return the amount of elements in this list */ int size(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/StackListEntry.java ================================================ package com.refinedmods.refinedstorage.api.util; import java.util.UUID; /** * Represents a stack in a stack list. * * @param the stack type */ public class StackListEntry { private final UUID id; private final T stack; public StackListEntry(T stack) { this.stack = stack; this.id = UUID.randomUUID(); } public StackListEntry(UUID id, T stack) { this.id = id; this.stack = stack; } /** * The unique id of the entry. * This id is NOT persisted, nor does it hold any relation to the contained stack. * It is randomly generated. * * @return the id */ public UUID getId() { return id; } /** * @return the stack */ public T getStack() { return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/api/util/StackListResult.java ================================================ package com.refinedmods.refinedstorage.api.util; import java.util.UUID; /** * Contains the result of a stack list manipulation. * * @param the stack type */ public class StackListResult { private final T stack; private final UUID id; private final int change; public StackListResult(T stack, UUID id, int change) { this.stack = stack; this.id = id; this.change = change; } /** * @return the stack */ public T getStack() { return stack; } /** * @return the id of the {@link StackListEntry} */ public UUID getId() { return id; } /** * @return the change/delta value, is positive if this was a stack addition, or negative if it's a stack removal */ public int getChange() { return change; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/API.java ================================================ package com.refinedmods.refinedstorage.apiimpl; import com.refinedmods.refinedstorage.api.IRSAPI; import com.refinedmods.refinedstorage.api.RSAPIInject; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry; import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior; import com.refinedmods.refinedstorage.api.network.grid.IGridManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IQuantityFormatter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementList; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.CraftingMonitorElementRegistry; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.CraftingPreviewElementRegistry; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.CraftingRequestInfo; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.CraftingTaskRegistry; import com.refinedmods.refinedstorage.apiimpl.network.NetworkManager; import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeManager; import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeRegistry; import com.refinedmods.refinedstorage.apiimpl.network.grid.CraftingGridBehavior; import com.refinedmods.refinedstorage.apiimpl.network.grid.GridManager; import com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskManager; import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskRegistry; import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskSync; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.StorageTrackerManager; import com.refinedmods.refinedstorage.apiimpl.util.Comparer; import com.refinedmods.refinedstorage.apiimpl.util.FluidStackList; import com.refinedmods.refinedstorage.apiimpl.util.ItemStackList; import com.refinedmods.refinedstorage.apiimpl.util.QuantityFormatter; import com.refinedmods.refinedstorage.util.StackUtils; import java.lang.reflect.Field; import java.util.Collection; import java.util.Collections; import java.util.EnumMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.saveddata.SavedData; import net.neoforged.fml.ModList; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforgespi.language.ModFileScanData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.objectweb.asm.Type; public class API implements IRSAPI { private static final Logger LOGGER = LogManager.getLogger(API.class); private static final IRSAPI INSTANCE = new API(); private final IComparer comparer = new Comparer(); private final IQuantityFormatter quantityFormatter = new QuantityFormatter(); private final INetworkNodeRegistry networkNodeRegistry = new NetworkNodeRegistry(); private final ICraftingTaskRegistry craftingTaskRegistry = new CraftingTaskRegistry(); private final ICraftingMonitorElementRegistry craftingMonitorElementRegistry = new CraftingMonitorElementRegistry(); private final ICraftingPreviewElementRegistry craftingPreviewElementRegistry = new CraftingPreviewElementRegistry(); private final IGridManager gridManager = new GridManager(); private final ICraftingGridBehavior craftingGridBehavior = new CraftingGridBehavior(); private final IStorageDiskRegistry storageDiskRegistry = new StorageDiskRegistry(); private final IStorageDiskSync storageDiskSync = new StorageDiskSync(); private final Map>> externalStorageProviders = new EnumMap<>(StorageType.class); private final List patternRenderHandlers = new LinkedList<>(); public static IRSAPI instance() { return INSTANCE; } public static void deliver() { Type annotationType = Type.getType(RSAPIInject.class); List annotations = ModList.get().getAllScanData().stream() .map(ModFileScanData::getAnnotations) .flatMap(Collection::stream) .filter(a -> annotationType.equals(a.annotationType())) .toList(); LOGGER.info("Found {} RS API injection {}", annotations.size(), annotations.size() == 1 ? "point" : "points"); for (ModFileScanData.AnnotationData annotation : annotations) { try { Class clazz = Class.forName(annotation.clazz().getClassName()); Field field = clazz.getField(annotation.memberName()); if (field.getType() == IRSAPI.class) { field.set(null, INSTANCE); } LOGGER.info("Injected RS API in {} {}", annotation.clazz().getClassName(), annotation.memberName()); } catch (ClassNotFoundException | IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException e) { LOGGER.error("Could not inject RS API in {} {}", annotation.clazz().getClassName(), annotation.memberName(), e); } } } @Nonnull @Override public IComparer getComparer() { return comparer; } @Override @Nonnull public IQuantityFormatter getQuantityFormatter() { return quantityFormatter; } @Override @Nonnull public INetworkNodeRegistry getNetworkNodeRegistry() { return networkNodeRegistry; } @Override public INetworkNodeManager getNetworkNodeManager(ServerLevel level) { return level.getDataStorage().computeIfAbsent(new SavedData.Factory<>( () -> new NetworkNodeManager(level), tag -> { NetworkNodeManager manager = new NetworkNodeManager(level); manager.load(tag); return manager; } ), NetworkNodeManager.NAME); } @Override public INetworkManager getNetworkManager(ServerLevel level) { return level.getDataStorage().computeIfAbsent(new SavedData.Factory<>( () -> new NetworkManager(level), tag -> { NetworkManager manager = new NetworkManager(level); manager.load(tag); return manager; } ), NetworkManager.NAME); } @Override @Nonnull public ICraftingTaskRegistry getCraftingTaskRegistry() { return craftingTaskRegistry; } @Override @Nonnull public ICraftingMonitorElementRegistry getCraftingMonitorElementRegistry() { return craftingMonitorElementRegistry; } @Override @Nonnull public ICraftingPreviewElementRegistry getCraftingPreviewElementRegistry() { return craftingPreviewElementRegistry; } @Nonnull @Override public IStackList createItemStackList() { return new ItemStackList(); } @Override @Nonnull public IStackList createFluidStackList() { return new FluidStackList(); } @Override @Nonnull public ICraftingMonitorElementList createCraftingMonitorElementList() { return new CraftingMonitorElementList(); } @Nonnull @Override public IGridManager getGridManager() { return gridManager; } @Nonnull @Override public ICraftingGridBehavior getCraftingGridBehavior() { return craftingGridBehavior; } @Nonnull @Override public IStorageDiskRegistry getStorageDiskRegistry() { return storageDiskRegistry; } @Nonnull @Override public IStorageDiskManager getStorageDiskManager(ServerLevel level) { ServerLevel overworld = level.getServer().overworld(); // Get the overworld return overworld.getDataStorage().computeIfAbsent(new SavedData.Factory<>( () -> new StorageDiskManager(overworld), tag -> { StorageDiskManager manager = new StorageDiskManager(overworld); manager.load(tag); return manager; } ), StorageDiskManager.NAME); } @Nonnull @Override public IStorageDiskSync getStorageDiskSync() { return storageDiskSync; } @Nonnull @Override public IStorageTrackerManager getStorageTrackerManager(ServerLevel level) { ServerLevel overworld = level.getServer().overworld(); // Get the overworld return overworld.getDataStorage().computeIfAbsent(new SavedData.Factory<>( StorageTrackerManager::new, tag -> { StorageTrackerManager manager = new StorageTrackerManager(); manager.load(tag); return manager; } ), StorageTrackerManager.NAME); } @Override public void addExternalStorageProvider(StorageType type, IExternalStorageProvider provider) { externalStorageProviders.computeIfAbsent(type, k -> new TreeSet<>((a, b) -> Integer.compare(b.getPriority(), a.getPriority()))).add(provider); } @Override public Set> getExternalStorageProviders(StorageType type) { TreeSet> providers = externalStorageProviders.get(type); return providers == null ? Collections.emptySet() : providers; } @Override @Nonnull public IStorageDisk createDefaultItemDisk(ServerLevel level, int capacity, @Nullable Player owner) { if (level == null) { throw new IllegalArgumentException("Level cannot be null"); } return new ItemStorageDisk(level, capacity, owner == null ? null : owner.getGameProfile().getId()); } @Override @Nonnull public IStorageDisk createDefaultFluidDisk(ServerLevel level, int capacity, @Nullable Player owner) { if (level == null) { throw new IllegalArgumentException("Level cannot be null"); } return new FluidStorageDisk(level, capacity, owner == null ? null : owner.getGameProfile().getId()); } @Override public ICraftingRequestInfo createCraftingRequestInfo(ItemStack stack, int count) { return new CraftingRequestInfo(ItemHandlerHelper.copyStackWithSize(stack, count)); } @Override public ICraftingRequestInfo createCraftingRequestInfo(FluidStack stack, int count) { return new CraftingRequestInfo(StackUtils.copy(stack, count)); } @Override public ICraftingRequestInfo createCraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException { return new CraftingRequestInfo(tag); } @Override public void addPatternRenderHandler(ICraftingPatternRenderHandler renderHandler) { patternRenderHandlers.add(renderHandler); } @Override public List getPatternRenderHandlers() { return patternRenderHandlers; } @Override public int getItemStackHashCode(ItemStack stack) { int result = stack.getItem().hashCode(); if (stack.hasTag()) { result = getHashCode(stack.getTag(), result); } return result; } private int getHashCode(Tag tag, int result) { if (tag instanceof CompoundTag) { result = getHashCode((CompoundTag) tag, result); } else if (tag instanceof ListTag) { result = getHashCode((ListTag) tag, result); } else { result = 31 * result + tag.hashCode(); } return result; } private int getHashCode(CompoundTag tag, int result) { for (String key : tag.getAllKeys()) { result = 31 * result + key.hashCode(); result = getHashCode(tag.get(key), result); } return result; } private int getHashCode(ListTag tag, int result) { for (Tag tagItem : tag) { result = getHashCode(tagItem, result); } return result; } @Override public int getFluidStackHashCode(FluidStack stack) { int result = stack.getFluid().hashCode(); if (stack.getTag() != null) { result = getHashCode(stack.getTag(), result); } return result; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/AllowedTagList.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class AllowedTagList { private static final String NBT_ALLOWED_ITEM_TAGS = "AllowedItemTags"; private static final String NBT_ALLOWED_FLUID_TAGS = "AllowedFluidTags"; @Nullable private final Runnable listener; private List> allowedItemTags = new ArrayList<>(); private List> allowedFluidTags = new ArrayList<>(); public AllowedTagList(@Nullable Runnable listener, int size) { for (int i = 0; i < size; ++i) { allowedItemTags.add(new HashSet<>()); allowedFluidTags.add(new HashSet<>()); } this.listener = listener; } public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); tag.put(NBT_ALLOWED_ITEM_TAGS, getList(allowedItemTags)); tag.put(NBT_ALLOWED_FLUID_TAGS, getList(allowedFluidTags)); return tag; } public void readFromNbt(CompoundTag tag) { if (tag.contains(NBT_ALLOWED_ITEM_TAGS)) { applyList(allowedItemTags, tag.getList(NBT_ALLOWED_ITEM_TAGS, Tag.TAG_LIST)); } if (tag.contains(NBT_ALLOWED_FLUID_TAGS)) { applyList(allowedFluidTags, tag.getList(NBT_ALLOWED_FLUID_TAGS, Tag.TAG_LIST)); } } private ListTag getList(List> tagsPerSlot) { ListTag list = new ListTag(); for (Set tags : tagsPerSlot) { ListTag subList = new ListTag(); tags.forEach(t -> subList.add(StringTag.valueOf(t.toString()))); list.add(subList); } return list; } private void applyList(List> list, ListTag tagList) { for (int i = 0; i < tagList.size(); ++i) { ListTag subList = tagList.getList(i); for (int j = 0; j < subList.size(); ++j) { list.get(i).add(new ResourceLocation(subList.getString(j))); } } } public List> getAllowedItemTags() { return allowedItemTags; } public void setAllowedItemTags(List> allowedItemTags) { this.allowedItemTags = allowedItemTags; notifyListener(); } public List> getAllowedFluidTags() { return allowedFluidTags; } public void setAllowedFluidTags(List> allowedFluidTags) { this.allowedFluidTags = allowedFluidTags; notifyListener(); } public void setAllowedItemTags(int slot, Set allowedItemTags) { this.allowedItemTags.set(slot, allowedItemTags); notifyListener(); } public void setAllowedFluidTags(int slot, Set allowedFluidTags) { this.allowedFluidTags.set(slot, allowedFluidTags); notifyListener(); } public void clearItemTags(int slot) { this.allowedItemTags.get(slot).clear(); notifyListener(); } public void clearFluidTags(int slot) { this.allowedFluidTags.get(slot).clear(); notifyListener(); } private void notifyListener() { if (listener != null) { listener.run(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener; import com.refinedmods.refinedstorage.api.autocrafting.task.*; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CalculationResult; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; public class CraftingManager implements ICraftingManager { private static final int THROTTLE_DELAY_MS = 3000; private static final Logger LOGGER = LogManager.getLogger(CraftingManager.class); private static final String NBT_TASKS = "Tasks"; private static final String NBT_TASK_TYPE = "Type"; private static final String NBT_TASK_DATA = "Task"; private final INetwork network; private final Map> containerInventories = new LinkedHashMap<>(); private final Map> patternToContainer = new HashMap<>(); private final List patterns = new ArrayList<>(); private final Map fluidPatternsByOutput = new HashMap<>(); private final Map itemPatternsByOutput = new HashMap<>(); private final Map tasks = new LinkedHashMap<>(); private final List tasksToAdd = new ArrayList<>(); private final List tasksToCancel = new ArrayList<>(); private final Map throttledRequesters = new HashMap<>(); private final Set listeners = new HashSet<>(); private ListTag tasksToRead; private static class FluidStackKey { private final Fluid fluid; private final CompoundTag tag; public FluidStackKey(FluidStack fluidStack) { this.fluid = fluidStack.getFluid(); this.tag = fluidStack.getTag(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; FluidStackKey that = (FluidStackKey) o; return fluid.equals(that.fluid) && Objects.equals(tag, that.tag); } @Override public int hashCode() { return Objects.hash(fluid, tag); } } private static class ItemStackKey { private final Item item; private final CompoundTag tag; public ItemStackKey(ItemStack itemStack) { this.item = itemStack.getItem(); this.tag = itemStack.getTag(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; ItemStackKey that = (ItemStackKey) o; return item.equals(that.item) && Objects.equals(tag, that.tag); } @Override public int hashCode() { return Objects.hash(item, tag); } } public CraftingManager(INetwork network) { this.network = network; } @Override public Collection getTasks() { return tasks.values(); } @Override @Nullable public ICraftingTask getTask(UUID id) { return tasks.get(id); } @Override public Map> getNamedContainers() { return containerInventories; } @Override public void start(@Nonnull ICraftingTask task) { task.start(); tasksToAdd.add(task); network.markDirty(); } @Override public void cancel(@Nullable UUID id) { if (id == null) { tasksToCancel.addAll(tasks.keySet()); } else { tasksToCancel.add(id); } network.markDirty(); } @Override public ICalculationResult create(ItemStack stack, int quantity) { ICraftingPattern pattern = getPattern(stack); if (pattern == null) { return new CalculationResult(CalculationResultType.NO_PATTERN); } ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId()); if (factory == null) { return new CalculationResult(CalculationResultType.NO_PATTERN); } return factory.create(network, API.instance().createCraftingRequestInfo(stack, quantity), quantity, pattern); } @Override public ICalculationResult create(FluidStack stack, int quantity) { ICraftingPattern pattern = getPattern(stack); if (pattern == null) { return new CalculationResult(CalculationResultType.NO_PATTERN); } ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(pattern.getCraftingTaskFactoryId()); if (factory == null) { return new CalculationResult(CalculationResultType.NO_PATTERN); } return factory.create(network, API.instance().createCraftingRequestInfo(stack, quantity), quantity, pattern); } @Override public void update() { if (network.canRun()) { if (tasksToRead != null) { readTasks(); } boolean changed = !tasksToCancel.isEmpty() || !tasksToAdd.isEmpty(); processTasksToCancel(); processTasksToAdd(); boolean anyFinished = updateTasks(); if (changed || anyFinished) { onTaskChanged(); } if (!tasks.isEmpty()) { network.markDirty(); } } } private void processTasksToCancel() { for (UUID idToCancel : tasksToCancel) { if (this.tasks.containsKey(idToCancel)) { this.tasks.get(idToCancel).onCancelled(); this.tasks.remove(idToCancel); } } this.tasksToCancel.clear(); } private void processTasksToAdd() { for (ICraftingTask task : this.tasksToAdd) { this.tasks.put(task.getId(), task); } this.tasksToAdd.clear(); } private boolean updateTasks() { boolean anyFinished = false; Iterator> it = tasks.entrySet().iterator(); while (it.hasNext()) { ICraftingTask task = it.next().getValue(); if (task.update()) { anyFinished = true; it.remove(); } } return anyFinished; } private void readTasks() { for (int i = 0; i < tasksToRead.size(); ++i) { CompoundTag taskTag = tasksToRead.getCompound(i); ResourceLocation taskType = new ResourceLocation(taskTag.getString(NBT_TASK_TYPE)); CompoundTag taskData = taskTag.getCompound(NBT_TASK_DATA); ICraftingTaskFactory factory = API.instance().getCraftingTaskRegistry().get(taskType); if (factory != null) { try { ICraftingTask task = factory.createFromNbt(network, taskData); tasks.put(task.getId(), task); } catch (CraftingTaskReadException e) { LOGGER.error("Could not deserialize crafting task", e); } } } this.tasksToRead = null; } @Override public void readFromNbt(CompoundTag tag) { this.tasksToRead = tag.getList(NBT_TASKS, Tag.TAG_COMPOUND); } @Override public CompoundTag writeToNbt(CompoundTag tag) { ListTag list = new ListTag(); for (ICraftingTask task : tasks.values()) { CompoundTag taskTag = new CompoundTag(); taskTag.putString(NBT_TASK_TYPE, task.getPattern().getCraftingTaskFactoryId().toString()); taskTag.put(NBT_TASK_DATA, task.writeToNbt(new CompoundTag())); list.add(taskTag); } tag.put(NBT_TASKS, list); return tag; } @Override public void addListener(ICraftingMonitorListener listener) { listeners.add(listener); listener.onAttached(); } @Override public void removeListener(ICraftingMonitorListener listener) { listeners.remove(listener); } @Override public void onTaskChanged() { listeners.forEach(ICraftingMonitorListener::onChanged); } @Override @Nullable public ICraftingTask request(Object source, ItemStack stack, int amount) { if (isThrottled(source)) { return null; } for (ICraftingTask task : getTasks()) { if (task.getRequested().getItem() != null && API.instance().getComparer().isEqualNoQuantity(task.getRequested().getItem(), stack)) { amount -= task.getQuantity(); } } if (amount > 0) { ICalculationResult result = create(stack, amount); if (result.isOk()) { start(result.getTask()); return result.getTask(); } else { throttle(source); } } return null; } @Nullable @Override public ICraftingTask request(Object source, FluidStack stack, int amount) { if (isThrottled(source)) { return null; } for (ICraftingTask task : getTasks()) { if (task.getRequested().getFluid() != null && API.instance().getComparer().isEqual(task.getRequested().getFluid(), stack, IComparer.COMPARE_NBT)) { amount -= task.getQuantity(); } } if (amount > 0) { ICalculationResult result = create(stack, amount); if (result.isOk()) { start(result.getTask()); return result.getTask(); } else { throttle(source); } } return null; } private void throttle(Object source) { if (source != null) { throttledRequesters.put(source, System.currentTimeMillis()); } } private boolean isThrottled(Object source) { if (source == null) { return false; } Long throttledSince = throttledRequesters.get(source); if (throttledSince == null) { return false; } return System.currentTimeMillis() - throttledSince < THROTTLE_DELAY_MS; } @Override public int track(@Nonnull ItemStack stack, int size) { if (stack.isEmpty()) { return 0; } for (ICraftingTask task : tasks.values()) { size = task.onTrackedInsert(stack, size); if (size == 0) { return 0; } } return size; } @Override public int track(@Nonnull FluidStack stack, int size) { if (stack.isEmpty()) { return 0; } for (ICraftingTask task : tasks.values()) { size = task.onTrackedInsert(stack, size); if (size == 0) { return 0; } } return size; } @Override public List getPatterns() { return patterns; } @Override public void invalidate() { this.network.getItemStorageCache().getCraftablesList().clear(); this.network.getFluidStorageCache().getCraftablesList().clear(); this.patterns.clear(); this.fluidPatternsByOutput.clear(); this.itemPatternsByOutput.clear(); this.containerInventories.clear(); this.patternToContainer.clear(); List containers = getContainers(); for (ICraftingPatternContainer container : containers) { for (ICraftingPattern pattern : container.getPatterns()) { this.patterns.add(pattern); for (ItemStack output : pattern.getOutputs()) { network.getItemStorageCache().getCraftablesList().add(output); this.itemPatternsByOutput.put(new ItemStackKey(output), pattern); } for (FluidStack output : pattern.getFluidOutputs()) { network.getFluidStorageCache().getCraftablesList().add(output); this.fluidPatternsByOutput.put(new FluidStackKey(output), pattern); } Set containersForPattern = this.patternToContainer.computeIfAbsent(pattern, key -> new LinkedHashSet<>()); containersForPattern.add(container); } IItemHandlerModifiable handler = container.getPatternInventory(); if (handler != null) { this.containerInventories.computeIfAbsent(container.getName(), k -> new ArrayList<>()).add(handler); } } this.network.getItemStorageCache().reAttachListeners(); this.network.getFluidStorageCache().reAttachListeners(); } private List getContainers() { List containers = new ArrayList<>(); for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) { if (entry.getNode() instanceof ICraftingPatternContainer && entry.getNode().isActive()) { containers.add((ICraftingPatternContainer) entry.getNode()); } } containers.sort((a, b) -> b.getPosition().compareTo(a.getPosition())); return containers; } @Override public Set getAllContainers(ICraftingPattern pattern) { return patternToContainer.getOrDefault(pattern, Collections.emptySet()); } @Nullable @Override public ICraftingPattern getPattern(ItemStack pattern) { return itemPatternsByOutput.get(new ItemStackKey(pattern)); } @Nullable @Override public ICraftingPattern getPattern(FluidStack pattern) { return fluidPatternsByOutput.get(new FluidStackKey(pattern)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPattern.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.TransientCraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.List; public class CraftingPattern implements ICraftingPattern { private final CraftingPatternContext context; private final boolean processing; private final boolean exact; @Nullable private final CraftingRecipe recipe; private final CraftingPatternInputs inputs; private final CraftingPatternOutputs outputs; @Nullable private final AllowedTagList allowedTagList; public CraftingPattern(CraftingPatternContext context, boolean processing, boolean exact, @Nullable CraftingRecipe recipe, CraftingPatternInputs inputs, CraftingPatternOutputs outputs, @Nullable AllowedTagList allowedTagList) { this.context = context; this.processing = processing; this.exact = exact; this.recipe = recipe; this.inputs = inputs; this.outputs = outputs; this.allowedTagList = allowedTagList; } @Nullable public AllowedTagList getAllowedTagList() { return allowedTagList; } @Override public ICraftingPatternContainer getContainer() { return context.getContainer(); } @Override public ItemStack getStack() { return context.getStack(); } @Override public boolean isValid() { return true; } @Nullable @Override public Component getErrorMessage() { return null; } @Override public boolean isProcessing() { return processing; } @Override public List> getInputs() { return inputs.getInputs(); } @Override public NonNullList getOutputs() { return outputs.getOutputs(); } public ItemStack getOutput(NonNullList took, RegistryAccess registryAccess) { if (processing) { throw new IllegalStateException("Cannot get crafting output from processing pattern"); } if (took.size() != inputs.getInputs().size()) { throw new IllegalArgumentException("The items that are taken (" + took.size() + ") should match the inputs for this pattern (" + inputs.getInputs().size() + ")"); } CraftingContainer craftingContainer = new DummyCraftingContainer(); for (int i = 0; i < took.size(); ++i) { craftingContainer.setItem(i, took.get(i)); } ItemStack result = recipe.assemble(craftingContainer, registryAccess); if (result.isEmpty()) { throw new IllegalStateException("Cannot have empty result"); } return result; } @Override public NonNullList getByproducts() { if (processing) { throw new IllegalStateException("Cannot get byproduct outputs from processing pattern"); } return outputs.getByproducts(); } @Override public NonNullList getByproducts(NonNullList took) { if (processing) { throw new IllegalStateException("Cannot get byproduct outputs from processing pattern"); } if (took.size() != inputs.getInputs().size()) { throw new IllegalArgumentException("The items that are taken (" + took.size() + ") should match the inputs for this pattern (" + inputs.getInputs().size() + ")"); } CraftingContainer craftingContainer = new DummyCraftingContainer(); for (int i = 0; i < took.size(); ++i) { craftingContainer.setItem(i, took.get(i)); } NonNullList remainingItems = recipe.getRemainingItems(craftingContainer); NonNullList sanitized = NonNullList.create(); for (ItemStack item : remainingItems) { if (!item.isEmpty()) { sanitized.add(item); } } return sanitized; } @Override public List> getFluidInputs() { return inputs.getFluidInputs(); } @Override public NonNullList getFluidOutputs() { return outputs.getFluidOutputs(); } @Override public ResourceLocation getCraftingTaskFactoryId() { return CraftingTaskFactory.ID; } @Override public boolean equals(Object otherObj) { if (!(otherObj instanceof ICraftingPattern)) { return false; } ICraftingPattern other = (ICraftingPattern) otherObj; if (other.isProcessing() != processing) { return false; } if ((other.getInputs().size() != inputs.getInputs().size()) || (other.getFluidInputs().size() != inputs.getFluidInputs().size()) || (other.getOutputs().size() != outputs.getOutputs().size()) || (other.getFluidOutputs().size() != outputs.getFluidOutputs().size())) { return false; } if (!processing && other.getByproducts().size() != outputs.getByproducts().size()) { return false; } for (int i = 0; i < inputs.getInputs().size(); ++i) { List inputsForSlot = inputs.getInputs().get(i); List otherInputsForSlot = other.getInputs().get(i); if (inputsForSlot.size() != otherInputsForSlot.size()) { return false; } for (int j = 0; j < inputsForSlot.size(); ++j) { if (!API.instance().getComparer().isEqual(inputsForSlot.get(j), otherInputsForSlot.get(j))) { return false; } } } for (int i = 0; i < inputs.getFluidInputs().size(); ++i) { List inputsForSlot = inputs.getFluidInputs().get(i); List otherInputsForSlot = other.getFluidInputs().get(i); if (inputsForSlot.size() != otherInputsForSlot.size()) { return false; } for (int j = 0; j < inputsForSlot.size(); ++j) { if (!API.instance().getComparer().isEqual(inputsForSlot.get(j), otherInputsForSlot.get(j), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) { return false; } } } for (int i = 0; i < outputs.getOutputs().size(); ++i) { if (!API.instance().getComparer().isEqual(outputs.getOutputs().get(i), other.getOutputs().get(i))) { return false; } } for (int i = 0; i < outputs.getFluidOutputs().size(); ++i) { if (!API.instance().getComparer().isEqual(outputs.getFluidOutputs().get(i), other.getFluidOutputs().get(i), IComparer.COMPARE_NBT | IComparer.COMPARE_QUANTITY)) { return false; } } if (!processing) { for (int i = 0; i < outputs.getByproducts().size(); ++i) { if (!API.instance().getComparer().isEqual(outputs.getByproducts().get(i), other.getByproducts().get(i))) { return false; } } } return true; } @Override public int hashCode() { int result = 0; result = 31 * result + (processing ? 1 : 0); result = 31 * result + (exact ? 1 : 0); for (List inputsForSlot : inputs.getInputs()) { for (ItemStack input : inputsForSlot) { result = 31 * result + API.instance().getItemStackHashCode(input); } } for (List inputsForSlot : inputs.getFluidInputs()) { for (FluidStack input : inputsForSlot) { result = 31 * result + API.instance().getFluidStackHashCode(input); } } for (ItemStack output : outputs.getOutputs()) { result = 31 * result + API.instance().getItemStackHashCode(output); } for (FluidStack output : outputs.getFluidOutputs()) { result = 31 * result + API.instance().getFluidStackHashCode(output); } for (ItemStack byproduct : outputs.getByproducts()) { result = 31 * result + API.instance().getItemStackHashCode(byproduct); } return result; } public static class DummyCraftingContainer extends TransientCraftingContainer { public DummyCraftingContainer() { super(new AbstractContainerMenu(null, 0) { @Override public ItemStack quickMoveStack(Player p_38941_, int p_38942_) { return ItemStack.EMPTY; } @Override public boolean stillValid(Player player) { return true; } }, 3, 3); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternContext.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import net.minecraft.world.item.ItemStack; public class CraftingPatternContext { private final ICraftingPatternContainer container; private final ItemStack stack; public CraftingPatternContext(ICraftingPatternContainer container, ItemStack stack) { this.container = container; this.stack = stack; } public ICraftingPatternContainer getContainer() { return container; } public ItemStack getStack() { return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.item.PatternItem; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import javax.annotation.Nullable; import net.minecraft.core.Holder; import net.minecraft.core.NonNullList; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; public class CraftingPatternFactory { public static final CraftingPatternFactory INSTANCE = new CraftingPatternFactory(); public ICraftingPattern create(Level level, ICraftingPatternContainer container, ItemStack stack) { CraftingPatternContext context = new CraftingPatternContext(container, stack); boolean processing = PatternItem.isProcessing(stack); boolean exact = PatternItem.isExact(stack); AllowedTagList allowedTagList = PatternItem.getAllowedTags(stack); List> inputs = new ArrayList<>(); NonNullList outputs = NonNullList.create(); NonNullList byproducts = NonNullList.create(); List> fluidInputs = new ArrayList<>(); NonNullList fluidOutputs = NonNullList.create(); CraftingRecipe recipe = null; try { if (processing) { for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE; ++i) { fillProcessingInputs(i, stack, inputs, outputs, allowedTagList); fillProcessingFluidInputs(i, stack, fluidInputs, fluidOutputs, allowedTagList); } if (outputs.isEmpty() && fluidOutputs.isEmpty()) { throw new CraftingPatternFactoryException( Component.translatable("misc.refinedstorage.pattern.error.processing_no_outputs")); } } else { CraftingContainer craftingContainer = new CraftingPattern.DummyCraftingContainer(); for (int i = 0; i < 9; ++i) { fillCraftingInputs(craftingContainer, stack, inputs, i); } Optional foundRecipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, craftingContainer, level) .map(RecipeHolder::value); if (foundRecipe.isPresent()) { recipe = foundRecipe.get(); byproducts = recipe.getRemainingItems(craftingContainer); ItemStack output = recipe.assemble(craftingContainer, level.registryAccess()); if (!output.isEmpty()) { outputs.add(output); if (!exact) { modifyCraftingInputsToUseAlternatives(recipe, inputs); } } else { throw new CraftingPatternFactoryException( Component.translatable("misc.refinedstorage.pattern.error.no_output")); } } else { throw new CraftingPatternFactoryException( Component.translatable("misc.refinedstorage.pattern.error.recipe_does_not_exist")); } } } catch (CraftingPatternFactoryException e) { return new InvalidCraftingPattern(context, e.getErrorMessage()); } return new CraftingPattern( context, processing, exact, recipe, new CraftingPatternInputs(inputs, fluidInputs), new CraftingPatternOutputs(outputs, byproducts, fluidOutputs), allowedTagList ); } private void fillProcessingInputs(int i, ItemStack stack, List> inputs, NonNullList outputs, @Nullable AllowedTagList allowedTagList) throws CraftingPatternFactoryException { ItemStack input = PatternItem.getInputSlot(stack, i); if (input.isEmpty()) { inputs.add(NonNullList.create()); } else { NonNullList possibilities = NonNullList.create(); possibilities.add(input.copy()); if (allowedTagList != null) { Collection tagsOfItem = BuiltInRegistries.ITEM.getResourceKey(input.getItem()) .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k) .map(holder -> holder.tags() .map(TagKey::location) .collect(Collectors.toSet()))) .orElse(Collections.emptySet()); Set declaredAllowedTags = allowedTagList.getAllowedItemTags().get(i); for (ResourceLocation declaredAllowedTag : declaredAllowedTags) { if (!tagsOfItem.contains(declaredAllowedTag)) { throw new CraftingPatternFactoryException( Component.translatable( "misc.refinedstorage.pattern.error.tag_no_longer_applicable", declaredAllowedTag.toString(), input.getHoverName() ) ); } else { TagKey tagKey = TagKey.create(Registries.ITEM, declaredAllowedTag); for (Holder element : BuiltInRegistries.ITEM.getTagOrEmpty(tagKey)) { possibilities.add(new ItemStack(element, input.getCount())); } } } } inputs.add(possibilities); } ItemStack output = PatternItem.getOutputSlot(stack, i); if (!output.isEmpty()) { outputs.add(output); } } private void fillProcessingFluidInputs(int i, ItemStack stack, List> fluidInputs, NonNullList fluidOutputs, @Nullable AllowedTagList allowedTagList) throws CraftingPatternFactoryException { FluidStack input = PatternItem.getFluidInputSlot(stack, i); if (input.isEmpty()) { fluidInputs.add(NonNullList.create()); } else { NonNullList possibilities = NonNullList.create(); possibilities.add(input.copy()); if (allowedTagList != null) { Collection tagsOfFluid = BuiltInRegistries.FLUID.getResourceKey(input.getFluid()) .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k) .map(holder -> holder.tags() .map(TagKey::location) .collect(Collectors.toSet()))) .orElse(Collections.emptySet()); Set declaredAllowedTags = allowedTagList.getAllowedFluidTags().get(i); for (ResourceLocation declaredAllowedTag : declaredAllowedTags) { if (!tagsOfFluid.contains(declaredAllowedTag)) { throw new CraftingPatternFactoryException( Component.translatable( "misc.refinedstorage.pattern.error.tag_no_longer_applicable", declaredAllowedTag.toString(), input.getDisplayName() ) ); } else { TagKey tagKey = TagKey.create(Registries.FLUID, declaredAllowedTag); for (Holder element : BuiltInRegistries.FLUID.getTagOrEmpty(tagKey)) { possibilities.add(new FluidStack(element, input.getAmount())); } } } } fluidInputs.add(possibilities); } FluidStack output = PatternItem.getFluidOutputSlot(stack, i); if (!output.isEmpty()) { fluidOutputs.add(output); } } private void fillCraftingInputs(CraftingContainer inv, ItemStack stack, List> inputs, int i) { ItemStack input = PatternItem.getInputSlot(stack, i); inputs.add(input.isEmpty() ? NonNullList.create() : NonNullList.of(ItemStack.EMPTY, input)); inv.setItem(i, input); } private void modifyCraftingInputsToUseAlternatives(CraftingRecipe recipe, List> inputs) { if (!recipe.getIngredients().isEmpty()) { inputs.clear(); for (int i = 0; i < recipe.getIngredients().size(); ++i) { inputs.add(i, NonNullList.of(ItemStack.EMPTY, recipe.getIngredients().get(i).getItems())); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternFactoryException.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import net.minecraft.network.chat.Component; public class CraftingPatternFactoryException extends Exception { private final transient Component errorMessage; public CraftingPatternFactoryException(Component errorMessage) { this.errorMessage = errorMessage; } public Component getErrorMessage() { return errorMessage; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternInputs.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; public class CraftingPatternInputs { private final List> inputs; private final List> fluidInputs; public CraftingPatternInputs(List> inputs, List> fluidInputs) { this.inputs = inputs; this.fluidInputs = fluidInputs; } public List> getInputs() { return inputs; } public List> getFluidInputs() { return fluidInputs; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/CraftingPatternOutputs.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class CraftingPatternOutputs { private final NonNullList outputs; private final NonNullList byproducts; private final NonNullList fluidOutputs; public CraftingPatternOutputs(NonNullList outputs, NonNullList byproducts, NonNullList fluidOutputs) { this.outputs = outputs; this.byproducts = byproducts; this.fluidOutputs = fluidOutputs; } public NonNullList getOutputs() { return outputs; } public NonNullList getByproducts() { return byproducts; } public NonNullList getFluidOutputs() { return fluidOutputs; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/InvalidCraftingPattern.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import net.minecraft.core.NonNullList; import net.minecraft.core.RegistryAccess; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.List; public class InvalidCraftingPattern implements ICraftingPattern { private static final String EXCEPTION_MESSAGE = "Crafting pattern is invalid"; private final CraftingPatternContext context; private final Component errorMessage; public InvalidCraftingPattern(CraftingPatternContext context, Component errorMessage) { this.context = context; this.errorMessage = errorMessage; } @Override public ICraftingPatternContainer getContainer() { return context.getContainer(); } @Override public ItemStack getStack() { return context.getStack(); } @Override public boolean isValid() { return false; } @Nullable @Override public Component getErrorMessage() { return errorMessage; } @Override public boolean isProcessing() { return false; } @Override public List> getInputs() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public NonNullList getOutputs() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public ItemStack getOutput(NonNullList took, RegistryAccess registryAccess) { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public NonNullList getByproducts() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public NonNullList getByproducts(NonNullList took) { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public List> getFluidInputs() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public NonNullList getFluidOutputs() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } @Override public ResourceLocation getCraftingTaskFactoryId() { throw new UnsupportedOperationException(EXCEPTION_MESSAGE); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementList.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList; import net.minecraft.resources.ResourceLocation; import java.util.*; public class CraftingMonitorElementList implements ICraftingMonitorElementList { private final List elements = new LinkedList<>(); private final Map> currentLists = new LinkedHashMap<>(); private final Map> currentCraftingLists = new LinkedHashMap<>(); private final Map> currentProcessingLists = new LinkedHashMap<>(); private final Map> currentStorageLists = new LinkedHashMap<>(); @Override public void directAdd(ICraftingMonitorElement element) { elements.add(element); } @Override public void addStorage(ICraftingMonitorElement element) { Map craftingElements = currentCraftingLists.get(element.getBaseId()); Map processingElements = currentProcessingLists.get(element.getBaseId()); Map storedElements = currentStorageLists.get(element.getBaseId()); boolean merged = false; if (craftingElements != null) { ICraftingMonitorElement existingElement = craftingElements.get(element.baseElementHashCode()); if (existingElement != null) { if (existingElement instanceof ErrorCraftingMonitorElement) { ((ErrorCraftingMonitorElement) existingElement).mergeBases(element); } else { existingElement.merge(element); } merged = true; } } if (processingElements != null) { ICraftingMonitorElement existingElement = processingElements.get(element.baseElementHashCode()); if (existingElement != null) { if (existingElement instanceof ErrorCraftingMonitorElement) { ((ErrorCraftingMonitorElement) existingElement).mergeBases(element); } else { existingElement.merge(element); } merged = true; } } if (!merged) { if (storedElements == null) { storedElements = new HashMap<>(); } storedElements.put(element.baseElementHashCode(), element); currentStorageLists.put(element.getBaseId(), storedElements); } } @Override public void add(ICraftingMonitorElement element, boolean isProcessing) { Map currentElements = isProcessing ? currentProcessingLists.get(element.getBaseId()) : currentCraftingLists.get(element.getBaseId()); if (currentElements == null) { currentElements = new LinkedHashMap<>(); } ICraftingMonitorElement existingElement = currentElements.get(element.baseElementHashCode()); if (existingElement == null) { existingElement = element; } else { existingElement.merge(element); } currentElements.put(existingElement.baseElementHashCode(), existingElement); if (isProcessing) { currentProcessingLists.put(existingElement.getBaseId(), currentElements); } else { currentCraftingLists.put(existingElement.getBaseId(), currentElements); } } @Override public void add(ICraftingMonitorElement element) { Map currentElements = currentLists.get(element.getId()); if (currentElements == null) { currentElements = new HashMap<>(); } ICraftingMonitorElement exitingElement = currentElements.get(element.elementHashCode()); if (exitingElement == null) { exitingElement = element; } else { exitingElement.merge(element); } currentElements.put(exitingElement.elementHashCode(), exitingElement); currentLists.put(exitingElement.getId(), currentElements); } @Override public void commit() { currentLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add); currentLists.clear(); currentCraftingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add); currentCraftingLists.clear(); currentProcessingLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add); currentProcessingLists.clear(); currentStorageLists.values().stream().map(Map::values).flatMap(Collection::stream).forEach(elements::add); currentStorageLists.clear(); } @Override public List getElements() { if (!currentLists.isEmpty() || !currentCraftingLists.isEmpty() || !currentProcessingLists.isEmpty() || !currentStorageLists.isEmpty()) { commit(); } return elements; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/CraftingMonitorElementRegistry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementRegistry; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.function.Function; public class CraftingMonitorElementRegistry implements ICraftingMonitorElementRegistry { private final Map> registry = new HashMap<>(); @Override public void add(ResourceLocation id, Function factory) { registry.put(id, factory); } @Nullable @Override public Function get(ResourceLocation id) { return registry.get(id); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/ErrorCraftingMonitorElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.util.PacketBufferUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class ErrorCraftingMonitorElement implements ICraftingMonitorElement { public static final ResourceLocation ID = new ResourceLocation("error"); private final ICraftingMonitorElement base; private final String message; public ErrorCraftingMonitorElement(ICraftingMonitorElement base, String message) { this.base = base; this.message = message; } public static ErrorCraftingMonitorElement read(FriendlyByteBuf buf) { ResourceLocation id = buf.readResourceLocation(); String message = PacketBufferUtils.readString(buf); return new ErrorCraftingMonitorElement( API.instance().getCraftingMonitorElementRegistry().get(id).apply(buf), message ); } @Override public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { base.draw(graphics, x, y, drawers); drawers.getErrorDrawer().draw(graphics, x, y, null); } @Nullable @Override public List getTooltip() { List items = new ArrayList<>(base.getTooltip()); items.add(Component.translatable(message).setStyle(Styles.RED)); return items; } @Override public ResourceLocation getId() { return ID; } @Override public ResourceLocation getBaseId() { return base.getId(); } @Override public void write(FriendlyByteBuf buf) { buf.writeResourceLocation(base.getId()); buf.writeUtf(message); base.write(buf); } @Override public boolean merge(ICraftingMonitorElement element) { return elementHashCode() == element.elementHashCode() && base.merge(((ErrorCraftingMonitorElement) element).base); } @Override public int baseElementHashCode() { return base.elementHashCode(); } @Override public int elementHashCode() { return base.elementHashCode() ^ message.hashCode(); } public void mergeBases(ICraftingMonitorElement element) { this.base.merge(element); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/FluidCraftingMonitorElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.Collections; import java.util.List; public class FluidCraftingMonitorElement implements ICraftingMonitorElement { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "fluid"); private static final int COLOR_PROCESSING = 0xFFD9EDF7; private static final int COLOR_MISSING = 0xFFF2DEDE; private static final int COLOR_SCHEDULED = 0xFFE8E5CA; private static final int COLOR_CRAFTING = 0xFFADDBC6; private final FluidStack stack; private int stored; private int missing; private int processing; private int scheduled; private int crafting; public FluidCraftingMonitorElement(FluidStack stack, int stored, int missing, int processing, int scheduled, int crafting) { this.stack = stack; this.stored = stored; this.missing = missing; this.processing = processing; this.scheduled = scheduled; this.crafting = crafting; } public static FluidCraftingMonitorElement read(FriendlyByteBuf buf) { return new FluidCraftingMonitorElement( FluidStack.readFromPacket(buf), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt() ); } @Override @OnlyIn(Dist.CLIENT) public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { if (missing > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_MISSING); } else if (processing > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_PROCESSING); } else if (scheduled > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_SCHEDULED); } else if (crafting > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_CRAFTING); } drawers.getFluidDrawer().draw(graphics, x + 4, y + 6, stack); float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F; PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); int yy = y + 7; if (stored > 0) { 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))); yy += 7; } if (missing > 0) { 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))); yy += 7; } if (processing > 0) { 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))); yy += 7; } if (scheduled > 0) { 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))); yy += 7; } if (crafting > 0) { 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))); } poseStack.popPose(); } @Override public ResourceLocation getBaseId() { return ID; } @Override public ResourceLocation getId() { return ID; } @Nullable @Override public List getTooltip() { return Collections.singletonList(stack.getDisplayName()); } @Override public void write(FriendlyByteBuf buf) { stack.writeToPacket(buf); buf.writeInt(stored); buf.writeInt(missing); buf.writeInt(processing); buf.writeInt(scheduled); buf.writeInt(crafting); } @Override public boolean merge(ICraftingMonitorElement element) { if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) { this.stored += ((FluidCraftingMonitorElement) element).stored; this.missing += ((FluidCraftingMonitorElement) element).missing; this.processing += ((FluidCraftingMonitorElement) element).processing; this.scheduled += ((FluidCraftingMonitorElement) element).scheduled; this.crafting += ((FluidCraftingMonitorElement) element).crafting; return true; } return false; } @Override public int baseElementHashCode() { return elementHashCode(); } @Override public int elementHashCode() { return API.instance().getFluidStackHashCode(stack); } public static class Builder { private final FluidStack stack; private int stored; private int missing; private int processing; private int scheduled; private int crafting; public Builder(FluidStack stack) { this.stack = stack; } public static FluidCraftingMonitorElement.Builder forStack(FluidStack stack) { return new FluidCraftingMonitorElement.Builder(stack); } public FluidCraftingMonitorElement.Builder stored(int stored) { this.stored = stored; return this; } public FluidCraftingMonitorElement.Builder missing(int missing) { this.missing = missing; return this; } public FluidCraftingMonitorElement.Builder processing(int processing) { this.processing = processing; return this; } public FluidCraftingMonitorElement.Builder scheduled(int scheduled) { this.scheduled = scheduled; return this; } public FluidCraftingMonitorElement.Builder crafting(int crafting) { this.crafting = crafting; return this; } public FluidCraftingMonitorElement build() { return new FluidCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/craftingmonitor/ItemCraftingMonitorElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.util.RenderUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import javax.annotation.Nullable; import java.util.List; public class ItemCraftingMonitorElement implements ICraftingMonitorElement { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "item"); private static final int COLOR_PROCESSING = 0xFFD9EDF7; private static final int COLOR_MISSING = 0xFFF2DEDE; private static final int COLOR_SCHEDULED = 0xFFE8E5CA; private static final int COLOR_CRAFTING = 0xFFADDBC6; private final ItemStack stack; private int stored; private int missing; private int processing; private int scheduled; private int crafting; public ItemCraftingMonitorElement(ItemStack stack, int stored, int missing, int processing, int scheduled, int crafting) { this.stack = stack; this.stored = stored; this.missing = missing; this.processing = processing; this.scheduled = scheduled; this.crafting = crafting; } public static ItemCraftingMonitorElement read(FriendlyByteBuf buf) { return new ItemCraftingMonitorElement( StackUtils.readItemStack(buf), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt() ); } @Override @OnlyIn(Dist.CLIENT) public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { if (missing > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_MISSING); } else if (processing > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_PROCESSING); } else if (scheduled > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_SCHEDULED); } else if (crafting > 0) { drawers.getOverlayDrawer().draw(graphics, x, y, COLOR_CRAFTING); } drawers.getItemDrawer().draw(graphics, x + 4, y + 6, stack); float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F; PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); int yy = y + 7; if (stored > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get("gui.refinedstorage.crafting_monitor.stored", stored)); yy += 7; } if (missing > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get("gui.refinedstorage.crafting_monitor.missing", missing)); yy += 7; } if (processing > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get("gui.refinedstorage.crafting_monitor.processing", processing)); yy += 7; } if (scheduled > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get("gui.refinedstorage.crafting_monitor.scheduled", scheduled)); yy += 7; } if (crafting > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy, scale), I18n.get("gui.refinedstorage.crafting_monitor.crafting", crafting)); } poseStack.popPose(); } @Override public ResourceLocation getBaseId() { return ID; } @Override public ResourceLocation getId() { return ID; } @Nullable @Override public List getTooltip() { return RenderUtils.getTooltipFromItem(this.stack); } @Override public void write(FriendlyByteBuf buf) { StackUtils.writeItemStack(buf, stack); buf.writeInt(stored); buf.writeInt(missing); buf.writeInt(processing); buf.writeInt(scheduled); buf.writeInt(crafting); } @Override public boolean merge(ICraftingMonitorElement element) { if (element.getId().equals(getId()) && elementHashCode() == element.elementHashCode()) { this.stored += ((ItemCraftingMonitorElement) element).stored; this.missing += ((ItemCraftingMonitorElement) element).missing; this.processing += ((ItemCraftingMonitorElement) element).processing; this.scheduled += ((ItemCraftingMonitorElement) element).scheduled; this.crafting += ((ItemCraftingMonitorElement) element).crafting; return true; } return false; } @Override public int baseElementHashCode() { return elementHashCode(); } @Override public int elementHashCode() { return API.instance().getItemStackHashCode(stack); } public static class Builder { private final ItemStack stack; private int stored; private int missing; private int processing; private int scheduled; private int crafting; public Builder(ItemStack stack) { this.stack = stack; } public static Builder forStack(ItemStack stack) { return new Builder(stack); } public Builder stored(int stored) { this.stored = stored; return this; } public Builder missing(int missing) { this.missing = missing; return this; } public Builder processing(int processing) { this.processing = processing; return this; } public Builder scheduled(int scheduled) { this.scheduled = scheduled; return this; } public Builder crafting(int crafting) { this.crafting = crafting; return this; } public ItemCraftingMonitorElement build() { return new ItemCraftingMonitorElement(stack, stored, missing, processing, scheduled, crafting); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/CraftingPreviewElementRegistry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElementRegistry; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.function.Function; public class CraftingPreviewElementRegistry implements ICraftingPreviewElementRegistry { private final Map> registry = new HashMap<>(); @Override public void add(ResourceLocation id, Function factory) { registry.put(id, factory); } @Nullable @Override public Function get(ResourceLocation id) { return registry.get(id); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/ErrorCraftingPreviewElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; public class ErrorCraftingPreviewElement implements ICraftingPreviewElement { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "error"); private final CalculationResultType type; private final ItemStack recursedPattern; public ErrorCraftingPreviewElement(CalculationResultType type, ItemStack recursedPattern) { this.type = type; this.recursedPattern = recursedPattern; } public static ErrorCraftingPreviewElement read(FriendlyByteBuf buf) { int errorIdx = buf.readInt(); CalculationResultType error = errorIdx >= 0 && errorIdx < CalculationResultType.values().length ? CalculationResultType.values()[errorIdx] : CalculationResultType.TOO_COMPLEX; ItemStack stack = buf.readItem(); return new ErrorCraftingPreviewElement(error, stack); } public ItemStack getRecursedPattern() { return recursedPattern; } @Override public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { // NO OP } @Override public boolean doesDisableTaskStarting() { return true; } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(type.ordinal()); buf.writeItem(recursedPattern); } public CalculationResultType getType() { return type; } @Override public ResourceLocation getId() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/FluidCraftingPreviewElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.fluids.FluidStack; public class FluidCraftingPreviewElement implements ICraftingPreviewElement { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "fluid"); private final FluidStack stack; private int available; private boolean missing; // If missing is true then toCraft is the missing amount private int toCraft; public FluidCraftingPreviewElement(FluidStack stack) { this.stack = stack.copy(); } public FluidCraftingPreviewElement(FluidStack stack, int available, boolean missing, int toCraft) { this.stack = stack.copy(); this.available = available; this.missing = missing; this.toCraft = toCraft; } public static FluidCraftingPreviewElement read(FriendlyByteBuf buf) { FluidStack stack = FluidStack.readFromPacket(buf); int available = buf.readInt(); boolean missing = buf.readBoolean(); int toCraft = buf.readInt(); return new FluidCraftingPreviewElement(stack, available, missing, toCraft); } @Override public void write(FriendlyByteBuf buf) { stack.writeToPacket(buf); buf.writeInt(available); buf.writeBoolean(missing); buf.writeInt(toCraft); } public FluidStack getStack() { return stack; } @Override @OnlyIn(Dist.CLIENT) public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { if (missing) { drawers.getOverlayDrawer().draw(graphics, x, y, 0xFFF2DEDE); } x += 5; y += 7; drawers.getFluidDrawer().draw(graphics, x, y, getStack()); float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F; y += 2; PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); if (toCraft > 0) { String format = doesDisableTaskStarting() ? "gui.refinedstorage.crafting_preview.missing" : "gui.refinedstorage.crafting_preview.to_craft"; drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(format, API.instance().getQuantityFormatter().formatInBucketForm(toCraft))); y += 7; } if (available > 0) { 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))); } poseStack.popPose(); } public void addAvailable(int amount) { this.available += amount; } public void addToCraft(int amount) { this.toCraft += amount; } public void setMissing(boolean missing) { this.missing = missing; } @Override public boolean doesDisableTaskStarting() { return missing; } @Override public ResourceLocation getId() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/preview/ItemCraftingPreviewElement.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.preview; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.api.distmarker.Dist; import net.neoforged.api.distmarker.OnlyIn; import net.neoforged.neoforge.items.ItemHandlerHelper; public class ItemCraftingPreviewElement implements ICraftingPreviewElement { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "item"); private final ItemStack stack; private int available; private boolean missing; // If missing is true then toCraft is the missing amount private int toCraft; public ItemCraftingPreviewElement(ItemStack stack) { this.stack = ItemHandlerHelper.copyStackWithSize(stack, 1); } public ItemCraftingPreviewElement(ItemStack stack, int available, boolean missing, int toCraft) { this.stack = stack; this.available = available; this.missing = missing; this.toCraft = toCraft; } public static ItemCraftingPreviewElement read(FriendlyByteBuf buf) { ItemStack stack = buf.readItem(); int available = buf.readInt(); boolean missing = buf.readBoolean(); int toCraft = buf.readInt(); return new ItemCraftingPreviewElement(stack, available, missing, toCraft); } public ItemStack getStack() { return stack; } @Override public void write(FriendlyByteBuf buf) { buf.writeItem(stack); buf.writeInt(available); buf.writeBoolean(missing); buf.writeInt(toCraft); } @Override @OnlyIn(Dist.CLIENT) public void draw(GuiGraphics graphics, int x, int y, IElementDrawers drawers) { if (missing) { drawers.getOverlayDrawer().draw(graphics, x, y, 0xFFF2DEDE); } x += 5; y += 7; drawers.getItemDrawer().draw(graphics, x, y, stack); float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F; y += 2; PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); if (toCraft > 0) { String format = doesDisableTaskStarting() ? "gui.refinedstorage.crafting_preview.missing" : "gui.refinedstorage.crafting_preview.to_craft"; drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get(format, toCraft)); y += 7; } if (available > 0) { drawers.getStringDrawer().draw(graphics, RenderUtils.getOffsetOnScale(x + 23, scale), RenderUtils.getOffsetOnScale(y, scale), I18n.get("gui.refinedstorage.crafting_preview.available", available)); } poseStack.popPose(); } public void addAvailable(int amount) { this.available += amount; } public void addToCraft(int amount) { this.toCraft += amount; } public void setMissing(boolean missing) { this.missing = missing; } @Override public boolean doesDisableTaskStarting() { return missing; } @Override public ResourceLocation getId() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/CraftingRequestInfo.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; public class CraftingRequestInfo implements ICraftingRequestInfo { private static final String NBT_FLUID = "Fluid"; private static final String NBT_STACK = "Stack"; private ItemStack item; private FluidStack fluid; public CraftingRequestInfo(CompoundTag tag) throws CraftingTaskReadException { if (!tag.getBoolean(NBT_FLUID)) { item = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK)); if (item.isEmpty()) { throw new CraftingTaskReadException("Extractor stack is empty"); } } else { fluid = FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_STACK)); if (fluid.isEmpty()) { throw new CraftingTaskReadException("Extractor fluid stack is empty"); } } } public CraftingRequestInfo(ItemStack item) { this.item = item; } public CraftingRequestInfo(FluidStack fluid) { this.fluid = fluid; } @Nullable @Override public ItemStack getItem() { return item; } @Nullable @Override public FluidStack getFluid() { return fluid; } @Override public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); tag.putBoolean(NBT_FLUID, fluid != null); if (fluid != null) { tag.put(NBT_STACK, fluid.writeToNBT(new CompoundTag())); } else { tag.put(NBT_STACK, StackUtils.serializeStackToNbt(item)); } return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/CraftingTaskRegistry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskFactory; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTaskRegistry; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class CraftingTaskRegistry implements ICraftingTaskRegistry { private final Map registry = new HashMap<>(); @Override public void add(ResourceLocation id, ICraftingTaskFactory factory) { registry.put(id, factory); } @Override @Nullable public ICraftingTaskFactory get(ResourceLocation id) { return registry.get(id); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/README.md ================================================ # Autocrafting Autocrafting has had several refactors. Some history: |RS version|Autocrafting version| |----------|--------------------| |v0.6|v1| |v1.0|v2| |v1.2|v3| |v1.6|v4| |v1.6.4|v5| |v1.8.3|v6| ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingPatternInputs.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class CraftingPatternInputs { private final NonNullList recipe = NonNullList.create(); private final List> itemIngredients = new ArrayList<>(); private final List> fluidIngredients = new ArrayList<>(); public CraftingPatternInputs(ICraftingPattern pattern) { fillOutRecipe(pattern); combineItemInputs(pattern); combineFluidInputs(pattern); } private void fillOutRecipe(ICraftingPattern pattern) { for (NonNullList inputsForSlot : pattern.getInputs()) { if (inputsForSlot.isEmpty()) { recipe.add(ItemStack.EMPTY); } else { recipe.add(inputsForSlot.get(0)); } } } private void combineItemInputs(ICraftingPattern pattern) { for (NonNullList inputsForSlot : pattern.getInputs()) { if (inputsForSlot.isEmpty()) { continue; } Ingredient matchingIngredient = findMatchingItemIngredient(inputsForSlot); if (matchingIngredient == null) { itemIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getCount())); } else { matchingIngredient.increaseCount(inputsForSlot.get(0).getCount()); } } } private void combineFluidInputs(ICraftingPattern pattern) { for (NonNullList inputsForSlot : pattern.getFluidInputs()) { if (inputsForSlot.isEmpty()) { continue; } Ingredient matchingIngredient = findMatchingFluidIngredient(inputsForSlot); if (matchingIngredient == null) { fluidIngredients.add(new Ingredient<>(inputsForSlot, inputsForSlot.get(0).getAmount())); } else { matchingIngredient.increaseCount(inputsForSlot.get(0).getAmount()); } } } @Nullable private Ingredient findMatchingItemIngredient(NonNullList inputsForSlot) { for (Ingredient existingIngredient : itemIngredients) { if (existingIngredient.getInputs().size() == inputsForSlot.size()) { boolean found = true; for (int i = 0; i < inputsForSlot.size(); i++) { if (!API.instance().getComparer().isEqualNoQuantity(existingIngredient.getInputs().get(i), inputsForSlot.get(i))) { found = false; break; } } if (found) { return existingIngredient; } } } return null; } @Nullable private Ingredient findMatchingFluidIngredient(NonNullList inputsForSlot) { for (Ingredient existingIngredient : fluidIngredients) { if (existingIngredient.getInputs().size() == inputsForSlot.size()) { boolean found = true; for (int i = 0; i < inputsForSlot.size(); i++) { if (!API.instance().getComparer().isEqual(existingIngredient.getInputs().get(i), inputsForSlot.get(i), IComparer.COMPARE_NBT)) { found = false; break; } } if (found) { return existingIngredient; } } } return null; } public NonNullList getRecipe() { return recipe; } public List> getItemIngredients() { return itemIngredients; } public List> getFluidIngredients() { return fluidIngredients; } public static class Ingredient { private final NonNullList inputs; private int count; public Ingredient(NonNullList inputs, int count) { this.inputs = inputs; this.count = count; } public NonNullList getInputs() { return inputs; } public int getCount() { return count; } public void increaseCount(int count) { this.count += count; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingTask.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.monitor.CraftingMonitorElementFactory; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeList; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeListener; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode; import com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class CraftingTask implements ICraftingTask, NodeListener { private static final String NBT_REQUESTED = "Requested"; private static final String NBT_QUANTITY = "Quantity"; private static final String NBT_PATTERN = "Pattern"; private static final String NBT_TICKS = "Ticks"; private static final String NBT_ID = "Id"; private static final String NBT_EXECUTION_STARTED = "ExecutionStarted"; private static final String NBT_INTERNAL_STORAGE = "InternalStorage"; private static final String NBT_INTERNAL_FLUID_STORAGE = "InternalFluidStorage"; private static final String NBT_TO_EXTRACT_INITIAL = "ToExtractInitial"; private static final String NBT_TO_EXTRACT_INITIAL_FLUIDS = "ToExtractInitialFluids"; private static final String NBT_CRAFTS = "Crafts"; private static final String NBT_TOTAL_STEPS = "TotalSteps"; private static final String NBT_CURRENT_STEP = "CurrentStep"; private final IStorageDisk internalStorage; private final IStorageDisk internalFluidStorage; private final INetwork network; private final ICraftingRequestInfo requested; private final int quantity; private final ICraftingPattern pattern; private final UUID id; private final NodeList nodes; private final IStackList toExtractInitial; private final IStackList toExtractInitialFluids; private final CraftingMonitorElementFactory craftingMonitorElementFactory = new CraftingMonitorElementFactory(); private int ticks; private long startTime = -1; private int totalSteps; private int currentStep; public CraftingTask(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern, NodeList nodes, IStackList toExtractInitial, IStackList toExtractInitialFluids) { this.network = network; this.requested = requested; this.quantity = quantity; this.pattern = pattern; this.id = UUID.randomUUID(); this.nodes = nodes; this.internalStorage = new ItemStorageDisk(null, -1, null); this.internalFluidStorage = new FluidStorageDisk(null, -1, null); this.toExtractInitial = toExtractInitial; this.toExtractInitialFluids = toExtractInitialFluids; } public CraftingTask(INetwork network, CompoundTag tag) throws CraftingTaskReadException { this.network = network; this.requested = API.instance().createCraftingRequestInfo(tag.getCompound(NBT_REQUESTED)); this.quantity = tag.getInt(NBT_QUANTITY); this.pattern = SerializationUtil.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getLevel()); this.id = tag.getUUID(NBT_ID); this.nodes = new NodeList(); this.ticks = tag.getInt(NBT_TICKS); this.startTime = tag.getLong(NBT_EXECUTION_STARTED); this.totalSteps = tag.getInt(NBT_TOTAL_STEPS); this.currentStep = tag.getInt(NBT_CURRENT_STEP); this.internalStorage = new ItemStorageDiskFactory().createFromNbt(null, tag.getCompound(NBT_INTERNAL_STORAGE)); this.internalFluidStorage = new FluidStorageDiskFactory().createFromNbt(null, tag.getCompound(NBT_INTERNAL_FLUID_STORAGE)); this.toExtractInitial = SerializationUtil.readItemStackList(tag.getList(NBT_TO_EXTRACT_INITIAL, Tag.TAG_COMPOUND)); this.toExtractInitialFluids = SerializationUtil.readFluidStackList(tag.getList(NBT_TO_EXTRACT_INITIAL_FLUIDS, Tag.TAG_COMPOUND)); ListTag nodeList = tag.getList(NBT_CRAFTS, Tag.TAG_COMPOUND); for (int i = 0; i < nodeList.size(); ++i) { Node node = Node.fromNbt(network, nodeList.getCompound(i)); nodes.put(node.getPattern(), node); } } @Override public CompoundTag writeToNbt(CompoundTag tag) { tag.put(NBT_REQUESTED, requested.writeToNbt()); tag.putInt(NBT_QUANTITY, quantity); tag.put(NBT_PATTERN, SerializationUtil.writePatternToNbt(pattern)); tag.putInt(NBT_TICKS, ticks); tag.putUUID(NBT_ID, id); tag.putLong(NBT_EXECUTION_STARTED, startTime); tag.put(NBT_INTERNAL_STORAGE, internalStorage.writeToNbt()); tag.put(NBT_INTERNAL_FLUID_STORAGE, internalFluidStorage.writeToNbt()); tag.put(NBT_TO_EXTRACT_INITIAL, SerializationUtil.writeItemStackList(toExtractInitial)); tag.put(NBT_TO_EXTRACT_INITIAL_FLUIDS, SerializationUtil.writeFluidStackList(toExtractInitialFluids)); tag.putInt(NBT_TOTAL_STEPS, totalSteps); tag.putInt(NBT_CURRENT_STEP, currentStep); ListTag nodeList = new ListTag(); for (Node node : this.nodes.all()) { nodeList.add(node.writeToNbt()); } tag.put(NBT_CRAFTS, nodeList); return tag; } @Override public void start() { nodes.all().forEach(node -> { totalSteps += node.getQuantity(); node.onCalculationFinished(); }); startTime = System.currentTimeMillis(); IoUtil.extractItemsFromNetwork(toExtractInitial, network, internalStorage); IoUtil.extractFluidsFromNetwork(toExtractInitialFluids, network, internalFluidStorage); } @Override public int getCompletionPercentage() { if (totalSteps == 0) { return 0; } return (int) ((float) currentStep * 100 / totalSteps); } @Override public boolean update() { ++ticks; if (nodes.isEmpty()) { List toPerform = new ArrayList<>(); for (ItemStack stack : internalStorage.getStacks()) { ItemStack remainder = network.insertItem(stack, stack.getCount(), Action.PERFORM); toPerform.add(() -> internalStorage.extract(stack, stack.getCount() - remainder.getCount(), IComparer.COMPARE_NBT, Action.PERFORM)); } for (FluidStack stack : internalFluidStorage.getStacks()) { FluidStack remainder = network.insertFluid(stack, stack.getAmount(), Action.PERFORM); toPerform.add(() -> internalFluidStorage.extract(stack, stack.getAmount() - remainder.getAmount(), IComparer.COMPARE_NBT, Action.PERFORM)); } // Prevent CME. toPerform.forEach(Runnable::run); return internalStorage.getStacks().isEmpty() && internalFluidStorage.getStacks().isEmpty(); } else { IoUtil.extractItemsFromNetwork(toExtractInitial, network, internalStorage); IoUtil.extractFluidsFromNetwork(toExtractInitialFluids, network, internalFluidStorage); for (Node node : nodes.all()) { node.update(network, ticks, nodes, internalStorage, internalFluidStorage, this); } nodes.removeMarkedForRemoval(); return false; } } @Override public void onCancelled() { nodes.unlockAll(network); for (ItemStack remainder : internalStorage.getStacks()) { network.insertItem(remainder, remainder.getCount(), Action.PERFORM); } for (FluidStack remainder : internalFluidStorage.getStacks()) { network.insertFluid(remainder, remainder.getAmount(), Action.PERFORM); } } @Override public int getQuantity() { return quantity; } @Override public ICraftingRequestInfo getRequested() { return requested; } @Override public int onTrackedInsert(ItemStack stack, int size) { for (Node node : this.nodes.all()) { if (node instanceof ProcessingNode) { ProcessingNode processing = (ProcessingNode) node; int needed = processing.getNeeded(stack); if (needed > 0) { if (needed > size) { needed = size; } processing.markReceived(stack, needed); size -= needed; if (!processing.isRoot()) { internalStorage.insert(stack, needed, Action.PERFORM); } else { ItemStack remainder = network.insertItem(stack, needed, Action.PERFORM); internalStorage.insert(remainder, remainder.getCount(), Action.PERFORM); } network.getCraftingManager().onTaskChanged(); if (size == 0) { return 0; } } } } return size; } @Override public int onTrackedInsert(FluidStack stack, int size) { for (Node node : this.nodes.all()) { if (node instanceof ProcessingNode) { ProcessingNode processing = (ProcessingNode) node; int needed = processing.getNeeded(stack); if (needed > 0) { if (needed > size) { needed = size; } processing.markReceived(stack, needed); size -= needed; if (!processing.isRoot()) { internalFluidStorage.insert(stack, needed, Action.PERFORM); } else { FluidStack remainder = network.insertFluid(stack, needed, Action.PERFORM); internalFluidStorage.insert(remainder, remainder.getAmount(), Action.PERFORM); } network.getCraftingManager().onTaskChanged(); if (size == 0) { return 0; } } } } return size; } @Override public List getCraftingMonitorElements() { return craftingMonitorElementFactory.getElements(nodes.all(), internalStorage, internalFluidStorage); } @Override public ICraftingPattern getPattern() { return pattern; } @Override public long getStartTime() { return startTime; } @Override public UUID getId() { return id; } @Override public void onAllDone(Node node) { nodes.remove(node); } @Override public void onSingleDone(Node node) { currentStep++; network.getCraftingManager().onTaskChanged(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/CraftingTaskFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.task.*; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator.CraftingCalculator; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; public class CraftingTaskFactory implements ICraftingTaskFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "v6"); @Override public ICalculationResult create(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) { CraftingCalculator calculator = new CraftingCalculator(network, requested, quantity, pattern); return calculator.calculate(); } @Override public ICraftingTask createFromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException { return new CraftingTask(network, tag); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/IoUtil.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.List; public final class IoUtil { private static final int DEFAULT_EXTRACT_FLAGS = IComparer.COMPARE_NBT; private IoUtil() { } public static List extractFromInternalItemStorage(List list, IStorageDisk storage, Action action) { List extracted = new ArrayList<>(); for (ItemStack stack : list) { ItemStack result = storage.extract(stack, stack.getCount(), DEFAULT_EXTRACT_FLAGS, action); if (result.isEmpty() || result.getCount() != stack.getCount()) { if (action == Action.PERFORM) { throw new IllegalStateException("The internal crafting inventory reported that " + stack + " was available but we got " + result); } return null; } extracted.add(result); } return extracted; } public static List extractFromInternalFluidStorage(List list, IStorageDisk storage, Action action) { List extracted = new ArrayList<>(); for (FluidStack stack : list) { FluidStack result = storage.extract(stack, stack.getAmount(), DEFAULT_EXTRACT_FLAGS, action); if (result.isEmpty() || result.getAmount() != stack.getAmount()) { if (action == Action.PERFORM) { throw new IllegalStateException("The internal crafting inventory reported that " + stack + " was available but we got " + result); } return null; } extracted.add(result); } return extracted; } public static void extractItemsFromNetwork(IStackList toExtractInitial, INetwork network, IStorageDisk internalStorage) { if (toExtractInitial.isEmpty()) { return; } List toRemove = new ArrayList<>(); for (StackListEntry toExtract : toExtractInitial.getStacks()) { ItemStack result = network.extractItem(toExtract.getStack(), toExtract.getStack().getCount(), Action.PERFORM); if (!result.isEmpty()) { internalStorage.insert(toExtract.getStack(), result.getCount(), Action.PERFORM); toRemove.add(result); } } for (ItemStack stack : toRemove) { toExtractInitial.remove(stack); } if (!toRemove.isEmpty()) { network.getCraftingManager().onTaskChanged(); } } public static void extractFluidsFromNetwork(IStackList toExtractInitial, INetwork network, IStorageDisk internalStorage) { if (toExtractInitial.isEmpty()) { return; } List toRemove = new ArrayList<>(); for (StackListEntry toExtract : toExtractInitial.getStacks()) { FluidStack result = network.extractFluid(toExtract.getStack(), toExtract.getStack().getAmount(), Action.PERFORM); if (!result.isEmpty()) { internalStorage.insert(result, result.getAmount(), Action.PERFORM); toRemove.add(result); } } for (FluidStack stack : toRemove) { toExtractInitial.remove(stack); } if (!toRemove.isEmpty()) { network.getCraftingManager().onTaskChanged(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/SerializationUtil.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; public class SerializationUtil { private static final String NBT_PATTERN_STACK = "Stack"; private static final String NBT_PATTERN_CONTAINER_POS = "ContainerPos"; private SerializationUtil() { } public static ListTag writeItemStackList(IStackList stacks) { ListTag list = new ListTag(); for (StackListEntry entry : stacks.getStacks()) { list.add(StackUtils.serializeStackToNbt(entry.getStack())); } return list; } public static IStackList readItemStackList(ListTag list) throws CraftingTaskReadException { IStackList stacks = API.instance().createItemStackList(); for (int i = 0; i < list.size(); ++i) { ItemStack stack = StackUtils.deserializeStackFromNbt(list.getCompound(i)); if (stack.isEmpty()) { throw new CraftingTaskReadException("Empty stack!"); } stacks.add(stack); } return stacks; } public static ListTag writeFluidStackList(IStackList stacks) { ListTag list = new ListTag(); for (StackListEntry entry : stacks.getStacks()) { list.add(entry.getStack().writeToNBT(new CompoundTag())); } return list; } public static IStackList readFluidStackList(ListTag list) throws CraftingTaskReadException { IStackList stacks = API.instance().createFluidStackList(); for (int i = 0; i < list.size(); ++i) { FluidStack stack = FluidStack.loadFluidStackFromNBT(list.getCompound(i)); if (stack.isEmpty()) { throw new CraftingTaskReadException("Empty stack!"); } stacks.add(stack); } return stacks; } public static CompoundTag writePatternToNbt(ICraftingPattern pattern) { CompoundTag tag = new CompoundTag(); tag.put(NBT_PATTERN_STACK, pattern.getStack().save(new CompoundTag())); tag.putLong(NBT_PATTERN_CONTAINER_POS, pattern.getContainer().getPosition().asLong()); return tag; } public static ICraftingPattern readPatternFromNbt(CompoundTag tag, Level level) throws CraftingTaskReadException { BlockPos containerPos = BlockPos.of(tag.getLong(NBT_PATTERN_CONTAINER_POS)); INetworkNode node = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(containerPos); if (node instanceof ICraftingPatternContainer) { ItemStack stack = ItemStack.of(tag.getCompound(NBT_PATTERN_STACK)); if (stack.getItem() instanceof ICraftingPatternProvider) { return ((ICraftingPatternProvider) stack.getItem()).create(level, stack, (ICraftingPatternContainer) node); } else { throw new CraftingTaskReadException("Pattern stack is not a crafting pattern provider"); } } else { throw new CraftingTaskReadException("Crafting pattern container doesn't exist anymore"); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CalculationResult.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import javax.annotation.Nullable; import java.util.Collections; import java.util.List; public class CalculationResult implements ICalculationResult { private final CalculationResultType type; private final ICraftingPattern recursedPattern; private final List previewElements; private final ICraftingTask craftingTask; public CalculationResult(CalculationResultType type) { this.type = type; this.recursedPattern = null; this.previewElements = Collections.emptyList(); this.craftingTask = null; } public CalculationResult(CalculationResultType type, ICraftingPattern recursedPattern) { this.type = type; this.recursedPattern = recursedPattern; this.previewElements = Collections.emptyList(); this.craftingTask = null; } public CalculationResult(CalculationResultType type, List previewElements, @Nullable ICraftingTask craftingTask) { this.type = type; this.recursedPattern = null; this.previewElements = previewElements; this.craftingTask = craftingTask; } @Override public CalculationResultType getType() { return type; } @Override public List getPreviewElements() { return previewElements; } @Nullable @Override public ICraftingTask getTask() { return craftingTask; } @Override public boolean isOk() { return type == CalculationResultType.OK; } @Override @Nullable public ICraftingPattern getRecursedPattern() { return recursedPattern; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CraftingCalculator.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingPatternInputs; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTask; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.NodeList; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewElementFactory; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview.CraftingPreviewInfo; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nullable; import java.util.HashSet; import java.util.List; import java.util.Set; public class CraftingCalculator { private final INetwork network; private final ICraftingRequestInfo requested; private final int quantity; private final ICraftingPattern pattern; private final Set patternsUsed = new HashSet<>(); private final CraftingPreviewInfo craftingPreviewInfo = new CraftingPreviewInfo(); private final NodeList nodes = new NodeList(); private final IStackList toExtractInitial = API.instance().createItemStackList(); private final IStackList toExtractInitialFluids = API.instance().createFluidStackList(); private long calculationStarted = -1; public CraftingCalculator(INetwork network, ICraftingRequestInfo requested, int quantity, ICraftingPattern pattern) { this.network = network; this.requested = requested; this.quantity = quantity; this.pattern = pattern; } public ICalculationResult calculate() { this.calculationStarted = System.currentTimeMillis(); IStackList results = API.instance().createItemStackList(); IStackList fluidResults = API.instance().createFluidStackList(); IStackList storageSource = network.getItemStorageCache().getList().copy(); IStackList fluidStorageSource = network.getFluidStorageCache().getList().copy(); int qtyPerCraft = getQuantityPerCraft(requested.getItem(), requested.getFluid(), pattern); int qty = ((quantity - 1) / qtyPerCraft) + 1; try { calculateInternal(qty, storageSource, fluidStorageSource, results, fluidResults, pattern, true); } catch (CraftingCalculatorException e) { return new CalculationResult(e.getType(), e.getRecursedPattern()); } if (requested.getItem() != null) { craftingPreviewInfo.getToCraft().add(ItemHandlerHelper.copyStackWithSize(requested.getItem(), qty * qtyPerCraft)); } else if (requested.getFluid() != null) { craftingPreviewInfo.getToCraftFluids().add(StackUtils.copy(requested.getFluid(), qty * qtyPerCraft)); } List previewElements = new CraftingPreviewElementFactory().getElements(craftingPreviewInfo); if (craftingPreviewInfo.hasMissing()) { return new CalculationResult(CalculationResultType.MISSING, previewElements, null); } return new CalculationResult( CalculationResultType.OK, previewElements, new CraftingTask(network, requested, quantity, pattern, nodes, toExtractInitial, toExtractInitialFluids) ); } private void calculateInternal( int qty, IStackList storageSource, IStackList fluidStorageSource, IStackList results, IStackList fluidResults, ICraftingPattern pattern, boolean root) throws CraftingCalculatorException { if (System.currentTimeMillis() - calculationStarted > RS.SERVER_CONFIG.getAutocrafting().getCalculationTimeoutMs()) { throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX, null); } if (!patternsUsed.add(pattern)) { throw new CraftingCalculatorException(CalculationResultType.RECURSIVE, pattern); } IStackList itemsToExtract = API.instance().createItemStackList(); IStackList fluidsToExtract = API.instance().createFluidStackList(); CraftingPatternInputs inputs = new CraftingPatternInputs(pattern); Node node = nodes.createOrAddToExistingNode(pattern, root, inputs.getRecipe(), qty); calculateForItems(qty, storageSource, fluidStorageSource, results, fluidResults, itemsToExtract, inputs, node); if (node instanceof CraftingNode) { ItemStack output = pattern.getOutput(inputs.getRecipe(), network.getLevel().registryAccess()); results.add(output, output.getCount() * qty); for (ItemStack byproduct : pattern.getByproducts(inputs.getRecipe())) { results.add(byproduct, byproduct.getCount() * qty); } } else if (node instanceof ProcessingNode) { ProcessingNode processing = (ProcessingNode) node; calculateForFluids(qty, storageSource, fluidStorageSource, results, fluidResults, inputs, fluidsToExtract, processing); for (ItemStack output : pattern.getOutputs()) { results.add(output, output.getCount() * qty); } for (FluidStack output : pattern.getFluidOutputs()) { fluidResults.add(output, output.getAmount() * qty); } } patternsUsed.remove(pattern); } private void calculateForItems(int qty, IStackList storageSource, IStackList fluidStorageSource, IStackList results, IStackList fluidResults, IStackList itemsToExtract, CraftingPatternInputs inputs, Node node) throws CraftingCalculatorException { int ingredientNumber = -1; for (CraftingPatternInputs.Ingredient ingredient : inputs.getItemIngredients()) { ingredientNumber++; PossibleInputs possibleInputs = new PossibleInputs<>(ingredient.getInputs()); possibleInputs.sort(storageSource, results); ItemStack possibleInput = possibleInputs.get(); ItemStack fromSelf = results.get(possibleInput); ItemStack fromNetwork = storageSource.get(possibleInput); int remaining = ingredient.getCount() * qty; if (remaining < 0) { // int overflow throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX); } while (remaining > 0) { if (fromSelf != null) { int toTake = Math.min(remaining, fromSelf.getCount()); node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount()); results.remove(fromSelf, toTake); remaining -= toTake; fromSelf = results.get(possibleInput); } if (fromNetwork != null && remaining > 0) { int toTake = Math.min(remaining, fromNetwork.getCount()); craftingPreviewInfo.getToTake().add(possibleInput, toTake); node.getRequirements().addItemRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount()); storageSource.remove(fromNetwork, toTake); remaining -= toTake; fromNetwork = storageSource.get(possibleInput); toExtractInitial.add(possibleInput, toTake); } if (remaining > 0) { ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput); if (subPattern != null) { int qtyPerCraft = getQuantityPerCraft(possibleInput, null, subPattern); int subQty = ((remaining - 1) / qtyPerCraft) + 1; calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false); fromSelf = results.get(possibleInput); if (fromSelf == null) { throw new IllegalStateException("Recursive calculation didn't yield anything"); } fromNetwork = storageSource.get(possibleInput); // fromSelf contains the amount crafted after the loop. craftingPreviewInfo.getToCraft().add(fromSelf.copy()); } else { if (!possibleInputs.cycle()) { // Give up. possibleInput = possibleInputs.get(); // Revert back to 0. craftingPreviewInfo.getMissing().add(possibleInput, remaining); itemsToExtract.add(possibleInput, remaining); remaining = 0; } else { // Retry with new input... possibleInput = possibleInputs.get(); fromSelf = results.get(possibleInput); fromNetwork = storageSource.get(possibleInput); } } } } } } private void calculateForFluids(int qty, IStackList storageSource, IStackList fluidStorageSource, IStackList results, IStackList fluidResults, CraftingPatternInputs inputs, IStackList fluidsToExtract, ProcessingNode node) throws CraftingCalculatorException { int ingredientNumber = -1; for (CraftingPatternInputs.Ingredient ingredient : inputs.getFluidIngredients()) { ingredientNumber++; PossibleInputs possibleInputs = new PossibleInputs<>(ingredient.getInputs()); possibleInputs.sort(fluidStorageSource, fluidResults); FluidStack possibleInput = possibleInputs.get(); FluidStack fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT); FluidStack fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT); int remaining = ingredient.getCount() * qty; if (remaining < 0) { // int overflow throw new CraftingCalculatorException(CalculationResultType.TOO_COMPLEX); } while (remaining > 0) { if (fromSelf != null) { int toTake = Math.min(remaining, fromSelf.getAmount()); node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount()); fluidResults.remove(possibleInput, toTake); remaining -= toTake; fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT); } if (fromNetwork != null && remaining > 0) { int toTake = Math.min(remaining, fromNetwork.getAmount()); node.getRequirements().addFluidRequirement(ingredientNumber, possibleInput, toTake, ingredient.getCount()); craftingPreviewInfo.getToTakeFluids().add(possibleInput, toTake); fluidStorageSource.remove(fromNetwork, toTake); remaining -= toTake; fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT); toExtractInitialFluids.add(possibleInput, toTake); } if (remaining > 0) { ICraftingPattern subPattern = network.getCraftingManager().getPattern(possibleInput); if (subPattern != null) { int qtyPerCraft = getQuantityPerCraft(null, possibleInput, subPattern); int subQty = ((remaining - 1) / qtyPerCraft) + 1; calculateInternal(subQty, storageSource, fluidStorageSource, results, fluidResults, subPattern, false); fromSelf = fluidResults.get(possibleInput, IComparer.COMPARE_NBT); if (fromSelf == null) { throw new IllegalStateException("Recursive fluid calculation didn't yield anything"); } fromNetwork = fluidStorageSource.get(possibleInput, IComparer.COMPARE_NBT); // fromSelf contains the amount crafted after the loop. craftingPreviewInfo.getToCraftFluids().add(fromSelf.copy()); } else { if (!possibleInputs.cycle()) { // Give up. possibleInput = possibleInputs.get(); // Revert back to 0. craftingPreviewInfo.getMissingFluids().add(possibleInput, remaining); fluidsToExtract.add(possibleInput, remaining); remaining = 0; } else { // Retry with new input... possibleInput = possibleInputs.get(); fromSelf = fluidResults.get(possibleInput); fromNetwork = fluidStorageSource.get(possibleInput); } } } } } } private int getQuantityPerCraft(@Nullable ItemStack item, @Nullable FluidStack fluid, ICraftingPattern pattern) { if (item != null) { return getQuantityPerCraftForItem(item, pattern); } else if (fluid != null) { return getQuantityPerCraftForFluid(fluid, pattern); } else { return 0; } } private int getQuantityPerCraftForFluid(FluidStack fluid, ICraftingPattern pattern) { int qty = 0; for (FluidStack output : pattern.getFluidOutputs()) { if (API.instance().getComparer().isEqual(output, fluid, IComparer.COMPARE_NBT)) { qty += output.getAmount(); } } return qty; } private int getQuantityPerCraftForItem(ItemStack item, ICraftingPattern pattern) { int qty = 0; for (ItemStack output : pattern.getOutputs()) { if (API.instance().getComparer().isEqualNoQuantity(output, item)) { qty += output.getCount(); if (!pattern.isProcessing()) { break; } } } return qty; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/CraftingCalculatorException.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import javax.annotation.Nullable; public class CraftingCalculatorException extends Exception { private final CalculationResultType type; @Nullable private final transient ICraftingPattern recursedPattern; public CraftingCalculatorException(CalculationResultType type) { this.type = type; this.recursedPattern = null; } public CraftingCalculatorException(CalculationResultType type, @Nullable ICraftingPattern recursedPattern) { this.type = type; this.recursedPattern = recursedPattern; } public CalculationResultType getType() { return type; } @Nullable public ICraftingPattern getRecursedPattern() { return recursedPattern; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/calculator/PossibleInputs.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.calculator; import com.refinedmods.refinedstorage.api.util.IStackList; import java.util.ArrayList; import java.util.List; public class PossibleInputs { private final List possibilities; private int pos; public PossibleInputs(List possibilities) { this.possibilities = new ArrayList<>(possibilities); } public T get() { return possibilities.get(pos); } // Return false if we're exhausted. public boolean cycle() { if (pos + 1 >= possibilities.size()) { pos = 0; return false; } pos++; return true; } public void sort(IStackList mutatedStorage, IStackList results) { possibilities.sort((a, b) -> { int ar = mutatedStorage.getCount(a); int br = mutatedStorage.getCount(b); return br - ar; }); possibilities.sort((a, b) -> { int ar = results.getCount(a); int br = results.getCount(b); return br - ar; }); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/monitor/CraftingMonitorElementFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.monitor; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElementList; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ErrorCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.FluidCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ItemCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.CraftingNode; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.Node; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingNode; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node.ProcessingState; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.Collection; import java.util.List; public class CraftingMonitorElementFactory { public List getElements(Collection nodes, IStorageDisk internalStorage, IStorageDisk internalFluidStorage) { ICraftingMonitorElementList list = API.instance().createCraftingMonitorElementList(); for (Node node : nodes) { if (node instanceof CraftingNode) { addForRecipe(list, (CraftingNode) node); } else { addForProcessing(list, (ProcessingNode) node); } } for (ItemStack stack : internalStorage.getStacks()) { list.addStorage(new ItemCraftingMonitorElement(stack, stack.getCount(), 0, 0, 0, 0)); } for (FluidStack stack : internalFluidStorage.getStacks()) { list.addStorage(new FluidCraftingMonitorElement(stack, stack.getAmount(), 0, 0, 0, 0)); } list.commit(); return list.getElements(); } private void addForProcessing(ICraftingMonitorElementList list, ProcessingNode node) { if (node.getState() == ProcessingState.PROCESSED) { return; } for (StackListEntry requirement : node.getSingleItemSetToRequire().getStacks()) { if (node.getCurrentlyProcessing() > 0) { ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder .forStack(requirement.getStack()) .processing(requirement.getStack().getCount() * node.getCurrentlyProcessing()) .build(); list.add(element, true); } } for (StackListEntry toReceive : node.getSingleItemSetToReceive().getStacks()) { int needed = node.getNeeded(toReceive.getStack()); if (needed > 0) { ICraftingMonitorElement element = ItemCraftingMonitorElement.Builder .forStack(toReceive.getStack()) .scheduled(needed) .build(); element = wrapWithProcessingState(element, node.getState(), "item"); list.add(element, true); } } for (StackListEntry requirement : node.getSingleFluidSetToRequire().getStacks()) { if (node.getCurrentlyProcessing() > 0) { ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder .forStack(requirement.getStack()) .processing(requirement.getStack().getAmount() * node.getCurrentlyProcessing()) .build(); list.add(element, true); } } for (StackListEntry toReceive : node.getSingleFluidSetToReceive().getStacks()) { int needed = node.getNeeded(toReceive.getStack()); if (needed > 0) { ICraftingMonitorElement element = FluidCraftingMonitorElement.Builder .forStack(toReceive.getStack()) .scheduled(needed) .build(); element = wrapWithProcessingState(element, node.getState(), "fluid"); list.add(element, true); } } } private ICraftingMonitorElement wrapWithProcessingState(ICraftingMonitorElement element, ProcessingState state, String type) { if (state == ProcessingState.MACHINE_DOES_NOT_ACCEPT) { return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.machine_does_not_accept_" + type); } else if (state == ProcessingState.MACHINE_NONE) { return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.machine_none"); } else if (state == ProcessingState.LOCKED) { return new ErrorCraftingMonitorElement(element, "gui.refinedstorage.crafting_monitor.crafter_is_locked"); } return element; } private void addForRecipe(ICraftingMonitorElementList list, CraftingNode node) { if (node.getQuantity() > 0) { for (ItemStack receive : node.getPattern().getOutputs()) { list.add(new ItemCraftingMonitorElement(receive, 0, 0, 0, 0, receive.getCount() * node.getQuantity()), false); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/CraftingNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class CraftingNode extends Node { private static final String NBT_RECIPE = "Recipe"; private final NonNullList recipe; public CraftingNode(ICraftingPattern pattern, boolean root, NonNullList recipe) { super(pattern, root); this.recipe = recipe; } public CraftingNode(INetwork network, CompoundTag tag) throws CraftingTaskReadException { super(network, tag); this.recipe = NonNullList.create(); ListTag tookList = tag.getList(NBT_RECIPE, Tag.TAG_COMPOUND); for (int i = 0; i < tookList.size(); ++i) { recipe.add(StackUtils.deserializeStackFromNbt(tookList.getCompound(i))); } } @Override public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk internalStorage, IStorageDisk internalFluidStorage, NodeListener listener) { for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) { int interval = container.getUpdateInterval(); if (interval < 0) { throw new IllegalStateException(container + " has an update interval of < 0"); } if (interval == 0 || ticks % interval == 0) { for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) { var simulatedRequirements = requirements.getSingleItemRequirementSet(true); if(simulatedRequirements == null) { return; } if (IoUtil.extractFromInternalItemStorage(simulatedRequirements, internalStorage, Action.SIMULATE) != null) { var actualRequirements = requirements.getSingleItemRequirementSet(false); if(actualRequirements == null) { return; } IoUtil.extractFromInternalItemStorage(actualRequirements, internalStorage, Action.PERFORM); ItemStack output = getPattern().getOutput(recipe, network.getLevel().registryAccess()); if (!isRoot()) { internalStorage.insert(output, output.getCount(), Action.PERFORM); } else { ItemStack remainder = network.insertItem(output, output.getCount(), Action.PERFORM); internalStorage.insert(remainder, remainder.getCount(), Action.PERFORM); } // Byproducts need to always be inserted in the internal storage for later reuse further in the task. // Regular outputs can be inserted into the network *IF* it's a root since it's *NOT* expected to be used later on. for (ItemStack byp : getPattern().getByproducts(recipe)) { internalStorage.insert(byp, byp.getCount(), Action.PERFORM); } next(); listener.onSingleDone(this); if (getQuantity() <= 0) { listener.onAllDone(this); return; } } else { break; } } } } } @Override public CompoundTag writeToNbt() { CompoundTag tag = super.writeToNbt(); ListTag tookList = new ListTag(); for (ItemStack took : this.recipe) { tookList.add(StackUtils.serializeStackToNbt(took)); } tag.put(NBT_RECIPE, tookList); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/Node.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public abstract class Node { private static final String NBT_PATTERN = "Pattern"; private static final String NBT_ROOT = "Root"; private static final String NBT_IS_PROCESSING = "IsProcessing"; private static final String NBT_QUANTITY = "Quantity"; private static final String NBT_QUANTITY_TOTAL = "TotalQuantity"; protected final NodeRequirements requirements = new NodeRequirements(); private final boolean root; private final ICraftingPattern pattern; protected int quantity; protected int totalQuantity; protected Node(ICraftingPattern pattern, boolean root) { this.pattern = pattern; this.root = root; } protected Node(INetwork network, CompoundTag tag) throws CraftingTaskReadException { this.quantity = tag.getInt(NBT_QUANTITY); this.totalQuantity = tag.getInt(NBT_QUANTITY_TOTAL); this.pattern = SerializationUtil.readPatternFromNbt(tag.getCompound(NBT_PATTERN), network.getLevel()); this.root = tag.getBoolean(NBT_ROOT); this.requirements.readFromNbt(tag); } public static Node fromNbt(INetwork network, CompoundTag tag) throws CraftingTaskReadException { return tag.getBoolean(NBT_IS_PROCESSING) ? new ProcessingNode(network, tag) : new CraftingNode(network, tag); } public abstract void update(INetwork network, int ticks, NodeList nodes, IStorageDisk internalStorage, IStorageDisk internalFluidStorage, NodeListener listener); public void onCalculationFinished() { this.totalQuantity = quantity; } public ICraftingPattern getPattern() { return pattern; } public int getQuantity() { return quantity; } public void addQuantity(int quantity) { this.quantity += quantity; } protected void next() { quantity--; } public boolean isRoot() { return root; } public NodeRequirements getRequirements() { return requirements; } public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); tag.putInt(NBT_QUANTITY, quantity); tag.putInt(NBT_QUANTITY_TOTAL, totalQuantity); tag.putBoolean(NBT_IS_PROCESSING, this instanceof ProcessingNode); tag.putBoolean(NBT_ROOT, root); tag.put(NBT_PATTERN, SerializationUtil.writePatternToNbt(pattern)); tag = requirements.writeToNbt(tag); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeList.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.network.INetwork; import net.minecraft.core.NonNullList; import net.minecraft.world.item.ItemStack; import java.util.*; public class NodeList { private final Map nodes = new LinkedHashMap<>(); private final List nodesToRemove = new ArrayList<>(); public void removeMarkedForRemoval() { for (Node node : nodesToRemove) { nodes.remove(node.getPattern()); } nodesToRemove.clear(); } public Collection all() { return nodes.values(); } public void unlockAll(INetwork network) { for (Node node : nodes.values()) { if (node instanceof ProcessingNode) { network.getCraftingManager().getAllContainers(node.getPattern()).forEach(ICraftingPatternContainer::unlock); } } } public boolean isEmpty() { return nodes.isEmpty(); } public void remove(Node node) { nodesToRemove.add(node); } public Node createOrAddToExistingNode(ICraftingPattern pattern, boolean root, NonNullList recipe, int qty) { Node node = nodes.computeIfAbsent(pattern, key -> createNode(key, root, recipe)); node.addQuantity(qty); return node; } private Node createNode(ICraftingPattern pattern, boolean root, NonNullList recipe) { return pattern.isProcessing() ? new ProcessingNode(pattern, root) : new CraftingNode(pattern, root, recipe); } public void put(ICraftingPattern pattern, Node node) { nodes.put(pattern, node); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; public interface NodeListener { void onAllDone(Node node); void onSingleDone(Node node); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/NodeRequirements.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; import com.google.common.primitives.Ints; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nullable; import java.util.*; public class NodeRequirements { private static final String NBT_ITEMS_TO_USE = "ItemsToUse"; private static final String NBT_FLUIDS_TO_USE = "FluidsToUse"; private static final String NBT_ITEMS_NEEDED_PER_CRAFT = "ItemsNeededPerCraft"; private static final String NBT_FLUIDS_NEEDED_PER_CRAFT = "FluidsNeededPerCraft"; private final Map> itemRequirements = new LinkedHashMap<>(); private final Map itemsNeededPerCraft = new LinkedHashMap<>(); private final Map> fluidRequirements = new LinkedHashMap<>(); private final Map fluidsNeededPerCraft = new LinkedHashMap<>(); @Nullable private List cachedSimulatedItemRequirementSet = null; @Nullable private List cachedSimulatedFluidRequirementSet = null; public void addItemRequirement(int ingredientNumber, ItemStack stack, int size, int perCraft) { if (!itemsNeededPerCraft.containsKey(ingredientNumber)) { itemsNeededPerCraft.put(ingredientNumber, perCraft); } IStackList list = itemRequirements.computeIfAbsent(ingredientNumber, key -> API.instance().createItemStackList()); list.add(stack, size); cachedSimulatedItemRequirementSet = null; } public void addFluidRequirement(int ingredientNumber, FluidStack stack, int size, int perCraft) { if (!fluidsNeededPerCraft.containsKey(ingredientNumber)) { fluidsNeededPerCraft.put(ingredientNumber, perCraft); } IStackList list = fluidRequirements.computeIfAbsent(ingredientNumber, key -> API.instance().createFluidStackList()); list.add(stack, size); cachedSimulatedFluidRequirementSet = null; } public List getSingleItemRequirementSet(boolean simulate) { List cached = cachedSimulatedItemRequirementSet; if (simulate && cached != null) { return cached; } List toReturn = new ArrayList<>(); for (int i = 0; i < itemRequirements.size(); i++) { int needed = itemsNeededPerCraft.get(i); if (!itemRequirements.get(i).isEmpty()) { Iterator> it = itemRequirements.get(i).getStacks().iterator(); while (needed > 0 && it.hasNext()) { ItemStack toUse = it.next().getStack(); if (needed < toUse.getCount()) { if (!simulate) { itemRequirements.get(i).remove(toUse, needed); } toReturn.add(ItemHandlerHelper.copyStackWithSize(toUse, needed)); needed = 0; } else { if (!simulate) { it.remove(); } toReturn.add(toUse); needed -= toUse.getCount(); } } } else { return null; } } cachedSimulatedItemRequirementSet = simulate ? toReturn : null; return toReturn; } public List getSingleFluidRequirementSet(boolean simulate) { List cached = cachedSimulatedFluidRequirementSet; if (simulate && cached != null) { return cached; } List toReturn = new ArrayList<>(); for (int i = 0; i < fluidRequirements.size(); i++) { int needed = fluidsNeededPerCraft.get(i); if (!fluidRequirements.get(i).isEmpty()) { Iterator> it = fluidRequirements.get(i).getStacks().iterator(); while (needed > 0 && it.hasNext()) { FluidStack toUse = it.next().getStack(); if (needed < toUse.getAmount()) { if (!simulate) { fluidRequirements.get(i).remove(toUse, needed); } FluidStack stack = toUse.copy(); stack.setAmount(needed); toReturn.add(stack); needed = 0; } else { if (!simulate) { it.remove(); } toReturn.add(toUse); needed -= toUse.getAmount(); } } } else { return null; } } cachedSimulatedFluidRequirementSet = simulate ? toReturn : null; return toReturn; } public void readFromNbt(CompoundTag tag) throws CraftingTaskReadException { ListTag itemRequirementsTag = tag.getList(NBT_ITEMS_TO_USE, Tag.TAG_LIST); for (int i = 0; i < itemRequirementsTag.size(); i++) { itemRequirements.put(i, SerializationUtil.readItemStackList(itemRequirementsTag.getList(i))); } List itemsNeededPerCraftTag = Ints.asList(tag.getIntArray(NBT_ITEMS_NEEDED_PER_CRAFT)); for (int i = 0; i < itemsNeededPerCraftTag.size(); i++) { itemsNeededPerCraft.put(i, itemsNeededPerCraftTag.get(i)); } ListTag fluidRequirementsTag = tag.getList(NBT_FLUIDS_TO_USE, Tag.TAG_LIST); for (int i = 0; i < fluidRequirementsTag.size(); i++) { fluidRequirements.put(i, SerializationUtil.readFluidStackList(fluidRequirementsTag.getList(i))); } List fluidsNeededPerCraftTag = Ints.asList(tag.getIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT)); for (int i = 0; i < fluidsNeededPerCraftTag.size(); i++) { fluidsNeededPerCraft.put(i, fluidsNeededPerCraftTag.get(i)); } } public CompoundTag writeToNbt(CompoundTag tag) { ListTag itemRequirementsTag = new ListTag(); for (IStackList list : itemRequirements.values()) { itemRequirementsTag.add(SerializationUtil.writeItemStackList(list)); } tag.put(NBT_ITEMS_TO_USE, itemRequirementsTag); tag.putIntArray(NBT_ITEMS_NEEDED_PER_CRAFT, Ints.toArray(itemsNeededPerCraft.values())); ListTag fluidRequirementsTag = new ListTag(); for (IStackList list : fluidRequirements.values()) { fluidRequirementsTag.add(SerializationUtil.writeFluidStackList(list)); } tag.put(NBT_FLUIDS_TO_USE, fluidRequirementsTag); tag.putIntArray(NBT_FLUIDS_NEEDED_PER_CRAFT, Ints.toArray(fluidsNeededPerCraft.values())); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/ProcessingNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.IoUtil; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.SerializationUtil; import com.refinedmods.refinedstorage.apiimpl.util.FluidStackList; import com.refinedmods.refinedstorage.apiimpl.util.ItemStackList; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; public class ProcessingNode extends Node { private static final String NBT_ITEMS_RECEIVED = "ItemsReceived"; private static final String NBT_FLUIDS_RECEIVED = "FluidsReceived"; private static final String NBT_SINGLE_ITEM_SET_TO_REQUIRE = "SingleItemSetToRequire"; private static final String NBT_SINGLE_FLUID_SET_TO_REQUIRE = "SingleFluidSetToRequire"; private static final String NBT_STATE = "State"; private final IStackList singleItemSetToReceive = API.instance().createItemStackList(); private final IStackList singleFluidSetToReceive = API.instance().createFluidStackList(); private IStackList singleItemSetToRequire; private IStackList singleFluidSetToRequire; private IStackList itemsReceived = API.instance().createItemStackList(); private IStackList fluidsReceived = API.instance().createFluidStackList(); private ProcessingState state = ProcessingState.READY; private int quantityFinished; public ProcessingNode(ICraftingPattern pattern, boolean root) { super(pattern, root); initSetsToReceive(); } public ProcessingNode(INetwork network, CompoundTag tag) throws CraftingTaskReadException { super(network, tag); this.itemsReceived = SerializationUtil.readItemStackList(tag.getList(NBT_ITEMS_RECEIVED, Tag.TAG_COMPOUND)); this.fluidsReceived = SerializationUtil.readFluidStackList(tag.getList(NBT_FLUIDS_RECEIVED, Tag.TAG_COMPOUND)); this.singleItemSetToRequire = SerializationUtil.readItemStackList(tag.getList(NBT_SINGLE_ITEM_SET_TO_REQUIRE, Tag.TAG_COMPOUND)); this.singleFluidSetToRequire = SerializationUtil.readFluidStackList(tag.getList(NBT_SINGLE_FLUID_SET_TO_REQUIRE, Tag.TAG_COMPOUND)); this.state = ProcessingState.values()[tag.getInt(NBT_STATE)]; initSetsToReceive(); } private void initSetsToReceive() { for (ItemStack output : getPattern().getOutputs()) { singleItemSetToReceive.add(output, output.getCount()); } for (FluidStack output : getPattern().getFluidOutputs()) { singleFluidSetToReceive.add(output, output.getAmount()); } } @Override public void update(INetwork network, int ticks, NodeList nodes, IStorageDisk internalStorage, IStorageDisk internalFluidStorage, NodeListener listener) { if (getQuantity() <= 0) { if (totalQuantity == quantityFinished) { listener.onAllDone(this); } return; } boolean allLocked = true; boolean allMissingMachine = true; boolean allRejected = true; ProcessingState originalState = state; for (ICraftingPatternContainer container : network.getCraftingManager().getAllContainers(getPattern())) { int interval = container.getUpdateInterval(); if (interval < 0) { throw new IllegalStateException(container + " has an update interval of < 0"); } if (interval == 0 || ticks % interval == 0) { for (int i = 0; i < container.getMaximumSuccessfulCraftingUpdates(); i++) { if (getQuantity() <= 0) { return; } if (container.isLocked()) { if (allLocked) { this.state = ProcessingState.LOCKED; } break; } else { allLocked = false; } if ((!singleItemSetToRequire.isEmpty() && !container.hasConnectedInventory()) || (!singleFluidSetToRequire.isEmpty() && !container.hasConnectedFluidInventory())) { if (allMissingMachine) { this.state = ProcessingState.MACHINE_NONE; } break; } else { allMissingMachine = false; } boolean hasAllRequirements = false; var simulatedRequirements = requirements.getSingleItemRequirementSet(true); if(simulatedRequirements == null) { return; } List extractedItems = IoUtil.extractFromInternalItemStorage(simulatedRequirements, internalStorage, Action.SIMULATE); List extractedFluids = null; if (extractedItems != null) { var simulatedFluidRequirements = requirements.getSingleFluidRequirementSet(true); if(simulatedFluidRequirements == null) { return; } extractedFluids = IoUtil.extractFromInternalFluidStorage(simulatedFluidRequirements, internalFluidStorage, Action.SIMULATE); if (extractedFluids != null) { hasAllRequirements = true; } } boolean canInsertFullAmount = false; if (hasAllRequirements) { canInsertFullAmount = container.insertItemsIntoInventory(extractedItems, Action.SIMULATE); if (canInsertFullAmount) { canInsertFullAmount = container.insertFluidsIntoInventory(extractedFluids, Action.SIMULATE); } } else { break; } if (!canInsertFullAmount) { if (allRejected) { this.state = ProcessingState.MACHINE_DOES_NOT_ACCEPT; } break; } else { allRejected = false; } this.state = ProcessingState.READY; var actualRequirements = requirements.getSingleItemRequirementSet(false); if(actualRequirements == null) { return; } extractedItems = IoUtil.extractFromInternalItemStorage(actualRequirements, internalStorage, Action.PERFORM); var actualFluidRequirements = requirements.getSingleFluidRequirementSet(false); if(actualFluidRequirements == null) { return; } extractedFluids = IoUtil.extractFromInternalFluidStorage(actualFluidRequirements, internalFluidStorage, Action.PERFORM); container.insertItemsIntoInventory(extractedItems, Action.PERFORM); container.insertFluidsIntoInventory(extractedFluids, Action.PERFORM); next(); listener.onSingleDone(this); container.onUsedForProcessing(); } } } if (originalState != state) { network.getCraftingManager().onTaskChanged(); } } public ProcessingState getState() { return state; } public IStackList getSingleItemSetToReceive() { return singleItemSetToReceive; } public IStackList getSingleFluidSetToReceive() { return singleFluidSetToReceive; } public IStackList getSingleItemSetToRequire() { return singleItemSetToRequire; } public IStackList getSingleFluidSetToRequire() { return singleFluidSetToRequire; } public int getNeeded(ItemStack stack) { return (singleItemSetToReceive.getCount(stack) * totalQuantity) - itemsReceived.getCount(stack); } public int getNeeded(FluidStack stack) { return (singleFluidSetToReceive.getCount(stack) * totalQuantity) - fluidsReceived.getCount(stack); } public int getCurrentlyProcessing() { int unprocessed = totalQuantity - quantity; return unprocessed - quantityFinished; } public void markReceived(ItemStack stack, int count) { itemsReceived.add(stack, count); updateFinishedQuantity(); } public void markReceived(FluidStack stack, int count) { fluidsReceived.add(stack, count); updateFinishedQuantity(); } public void updateFinishedQuantity() { int tempQuantityFinished = totalQuantity; for (StackListEntry toReceive : singleItemSetToReceive.getStacks()) { if (itemsReceived.get(toReceive.getStack()) != null) { int ratioReceived = itemsReceived.get(toReceive.getStack()).getCount() / toReceive.getStack().getCount(); if (tempQuantityFinished > ratioReceived) { tempQuantityFinished = ratioReceived; } } else { tempQuantityFinished = 0; } } for (StackListEntry toReceive : singleFluidSetToReceive.getStacks()) { if (fluidsReceived.get(toReceive.getStack()) != null) { int ratioReceived = fluidsReceived.get(toReceive.getStack()).getAmount() / toReceive.getStack().getAmount(); if (tempQuantityFinished > ratioReceived) { tempQuantityFinished = ratioReceived; } } else { tempQuantityFinished = 0; } } this.quantityFinished = tempQuantityFinished; } @Override public void onCalculationFinished() { super.onCalculationFinished(); this.singleItemSetToRequire = new ItemStackList(requirements.getSingleItemRequirementSet(true)); this.singleFluidSetToRequire = new FluidStackList(requirements.getSingleFluidRequirementSet(true)); } @Override public CompoundTag writeToNbt() { CompoundTag tag = super.writeToNbt(); tag.put(NBT_ITEMS_RECEIVED, SerializationUtil.writeItemStackList(itemsReceived)); tag.put(NBT_FLUIDS_RECEIVED, SerializationUtil.writeFluidStackList(fluidsReceived)); tag.put(NBT_SINGLE_ITEM_SET_TO_REQUIRE, SerializationUtil.writeItemStackList(singleItemSetToRequire)); tag.put(NBT_SINGLE_FLUID_SET_TO_REQUIRE, SerializationUtil.writeFluidStackList(singleFluidSetToRequire)); tag.putInt(NBT_STATE, state.ordinal()); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/node/ProcessingState.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.node; public enum ProcessingState { READY, MACHINE_NONE, MACHINE_DOES_NOT_ACCEPT, PROCESSED, LOCKED } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/preview/CraftingPreviewElementFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview; import com.google.common.collect.ImmutableList; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class CraftingPreviewElementFactory { public List getElements(CraftingPreviewInfo info) { Map map = new LinkedHashMap<>(); Map mapFluids = new LinkedHashMap<>(); for (StackListEntry stack : info.getMissing().getStacks()) { int hash = API.instance().getItemStackHashCode(stack.getStack()); ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack.getStack())); previewStack.setMissing(true); previewStack.addToCraft(stack.getStack().getCount()); } for (StackListEntry stack : info.getMissingFluids().getStacks()) { int hash = API.instance().getFluidStackHashCode(stack.getStack()); FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack.getStack())); previewStack.setMissing(true); previewStack.addToCraft(stack.getStack().getAmount()); } for (ItemStack stack : ImmutableList.copyOf(info.getToCraft()).reverse()) { int hash = API.instance().getItemStackHashCode(stack); ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack)); previewStack.addToCraft(stack.getCount()); } for (FluidStack stack : ImmutableList.copyOf(info.getToCraftFluids()).reverse()) { int hash = API.instance().getFluidStackHashCode(stack); FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack)); previewStack.addToCraft(stack.getAmount()); } for (StackListEntry stack : info.getToTake().getStacks()) { int hash = API.instance().getItemStackHashCode(stack.getStack()); ItemCraftingPreviewElement previewStack = map.computeIfAbsent(hash, key -> new ItemCraftingPreviewElement(stack.getStack())); previewStack.addAvailable(stack.getStack().getCount()); } for (StackListEntry stack : info.getToTakeFluids().getStacks()) { int hash = API.instance().getFluidStackHashCode(stack.getStack()); FluidCraftingPreviewElement previewStack = mapFluids.computeIfAbsent(hash, key -> new FluidCraftingPreviewElement(stack.getStack())); previewStack.addAvailable(stack.getStack().getAmount()); } List elements = new ArrayList<>(); elements.addAll(map.values()); elements.addAll(mapFluids.values()); return elements; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/autocrafting/task/v6/preview/CraftingPreviewInfo.java ================================================ package com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.preview; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.List; public class CraftingPreviewInfo { private final IStackList missing = API.instance().createItemStackList(); private final IStackList missingFluids = API.instance().createFluidStackList(); private final IStackList toTake = API.instance().createItemStackList(); private final IStackList toTakeFluids = API.instance().createFluidStackList(); private final List toCraft = new ArrayList<>(); private final List toCraftFluids = new ArrayList<>(); public IStackList getMissing() { return missing; } public IStackList getMissingFluids() { return missingFluids; } public boolean hasMissing() { return !missing.isEmpty() || !missingFluids.isEmpty(); } public IStackList getToTake() { return toTake; } public IStackList getToTakeFluids() { return toTakeFluids; } public List getToCraft() { return toCraft; } public List getToCraftFluids() { return toCraftFluids; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/Network.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraph; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.security.ISecurityManager; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingManager; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.FluidGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.ItemGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.item.NetworkItemManager; import com.refinedmods.refinedstorage.apiimpl.network.node.RootNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.security.SecurityManager; import com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker; import com.refinedmods.refinedstorage.block.ControllerBlock; import com.refinedmods.refinedstorage.energy.BaseEnergyStorage; import com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.Util; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.energy.IEnergyStorage; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import java.util.UUID; import java.util.function.Predicate; public class Network implements INetwork, IRedstoneConfigurable { private static final int THROTTLE_INACTIVE_TO_ACTIVE = 20; private static final int THROTTLE_ACTIVE_TO_INACTIVE = 4; private static final int THROTTLE_ENERGY_TYPE_CHANGE = 20; private static final String NBT_ENERGY = "Energy"; private static final String NBT_ITEM_STORAGE_TRACKER_ID = "ItemStorageTrackerId"; private static final String NBT_FLUID_STORAGE_TRACKER_ID = "FluidStorageTrackerId"; private static final Logger LOGGER = LogManager.getLogger(Network.class); private final IItemGridHandler itemGridHandler = new ItemGridHandler(this); private final IFluidGridHandler fluidGridHandler = new FluidGridHandler(this); private final INetworkItemManager networkItemManager = new NetworkItemManager(this); private final INetworkNodeGraph nodeGraph = new NetworkNodeGraph(this); private final ICraftingManager craftingManager = new CraftingManager(this); private final ISecurityManager securityManager = new SecurityManager(this); private final IStorageCache itemStorage = new ItemStorageCache(this); private final IStorageCache fluidStorage = new FluidStorageCache(this); private final BaseEnergyStorage energy = new BaseEnergyStorage(RS.SERVER_CONFIG.getController().getCapacity(), RS.SERVER_CONFIG.getController().getMaxTransfer(), 0); private final RootNetworkNode root; private final BlockPos pos; private final Level level; private final NetworkType type; private ItemStorageTracker itemStorageTracker; private UUID itemStorageTrackerId; private FluidStorageTracker fluidStorageTracker; private UUID fluidStorageTrackerId; private ControllerBlock.EnergyType lastEnergyType = ControllerBlock.EnergyType.OFF; private int lastEnergyUsage; private RedstoneMode redstoneMode = RedstoneMode.IGNORE; private boolean redstonePowered = false; private boolean amILoaded = false; private boolean throttlingDisabled = true; // Will be enabled after first update private boolean couldRun; private int ticksSinceUpdateChanged; private int ticksSinceEnergyTypeChanged; private int ticks; private long[] tickTimes = new long[100]; private int tickCounter = 0; public Network(Level level, BlockPos pos, NetworkType type) { this.pos = pos; this.level = level; this.type = type; this.root = new RootNetworkNode(this, level, pos); this.nodeGraph.addListener(() -> { if (!level.isLoaded(pos)) { return; } BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof ControllerBlockEntity) { ((ControllerBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(ControllerBlockEntity.NODES); } }); } public static int getEnergyScaled(int stored, int capacity, int scale) { return (int) ((float) stored / (float) capacity * (float) scale); } public static ControllerBlock.EnergyType getEnergyType(int stored, int capacity) { int energy = getEnergyScaled(stored, capacity, 100); if (energy <= 0) { return ControllerBlock.EnergyType.OFF; } else if (energy <= 10) { return ControllerBlock.EnergyType.NEARLY_OFF; } else if (energy <= 20) { return ControllerBlock.EnergyType.NEARLY_ON; } return ControllerBlock.EnergyType.ON; } public RootNetworkNode getRoot() { return root; } @Override public BlockPos getPosition() { return pos; } @Override public boolean canRun() { return amILoaded && energy.getEnergyStored() >= getEnergyUsage() && redstoneMode.isEnabled(redstonePowered); } public void setRedstonePowered(boolean redstonePowered) { this.redstonePowered = redstonePowered; } @Override public INetworkNodeGraph getNodeGraph() { return nodeGraph; } @Override public ISecurityManager getSecurityManager() { return securityManager; } @Override public ICraftingManager getCraftingManager() { return craftingManager; } @Override public void update() { if (!level.isClientSide) { long tickStart = Util.getNanos(); if (ticks == 0) { redstonePowered = level.hasNeighborSignal(pos); } ++ticks; amILoaded = level.isLoaded(pos); updateEnergyUsage(); if (canRun()) { craftingManager.update(); if (!craftingManager.getTasks().isEmpty()) { markDirty(); } } if (type == NetworkType.NORMAL) { if (!RS.SERVER_CONFIG.getController().getUseEnergy()) { energy.setStored(this.energy.getMaxEnergyStored()); } else { energy.extractEnergyBypassCanExtract(getEnergyUsage(), false); } } else if (type == NetworkType.CREATIVE) { energy.setStored(energy.getMaxEnergyStored()); } boolean canRun = canRun(); if (couldRun != canRun) { ++ticksSinceUpdateChanged; if ((canRun ? (ticksSinceUpdateChanged > THROTTLE_INACTIVE_TO_ACTIVE) : (ticksSinceUpdateChanged > THROTTLE_ACTIVE_TO_INACTIVE)) || throttlingDisabled) { ticksSinceUpdateChanged = 0; couldRun = canRun; throttlingDisabled = false; LOGGER.debug("Network at position {} changed running state to {}, causing an invalidation of the node graph", pos, couldRun); nodeGraph.invalidate(Action.PERFORM, level, pos); securityManager.invalidate(); } } else { ticksSinceUpdateChanged = 0; } ControllerBlock.EnergyType energyType = getEnergyType(); if (lastEnergyType != energyType) { ++ticksSinceEnergyTypeChanged; if (ticksSinceEnergyTypeChanged > THROTTLE_ENERGY_TYPE_CHANGE) { lastEnergyType = energyType; BlockState state = level.getBlockState(pos); if (state.getBlock() instanceof ControllerBlock) { level.setBlockAndUpdate(pos, state.setValue(ControllerBlock.ENERGY_TYPE, energyType)); } } } else { ticksSinceEnergyTypeChanged = 0; } tickTimes[tickCounter % tickTimes.length] = Util.getNanos() - tickStart; tickCounter++; } } @Override public IItemGridHandler getItemGridHandler() { return itemGridHandler; } @Override public IFluidGridHandler getFluidGridHandler() { return fluidGridHandler; } @Override public INetworkItemManager getNetworkItemManager() { return networkItemManager; } @Override public void onRemoved() { for (ICraftingTask task : craftingManager.getTasks()) { task.onCancelled(); } nodeGraph.disconnectAll(); API.instance().getStorageTrackerManager((ServerLevel) getLevel()).remove(itemStorageTrackerId); API.instance().getStorageTrackerManager((ServerLevel) getLevel()).remove(fluidStorageTrackerId); } @Override public IStorageCache getItemStorageCache() { return itemStorage; } @Override public IStorageCache getFluidStorageCache() { return fluidStorage; } @Override @Nonnull public ItemStack insertItem(@Nonnull ItemStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } if (itemStorage.getStorages().isEmpty()) { return ItemHandlerHelper.copyStackWithSize(stack, size); } ItemStack remainder = ItemHandlerHelper.copyStackWithSize(stack, size); int inserted = 0; int insertedExternally = 0; for (IStorage storage : this.itemStorage.getStorages()) { if (storage.getAccessType() == AccessType.EXTRACT) { continue; } int storedPre = storage.getStored(); remainder = storage.insert(remainder, size, action); if (action == Action.PERFORM) { inserted += storage.getCacheDelta(storedPre, size, remainder); } if (remainder.isEmpty()) { // The external storage is responsible for sending changes, we don't need to anymore if (storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); insertedExternally += size; } break; } else { // The external storage is responsible for sending changes, we don't need to anymore if (size != remainder.getCount() && storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); insertedExternally += size - remainder.getCount(); } size = remainder.getCount(); } } if (action == Action.PERFORM && inserted - insertedExternally > 0) { itemStorage.add(stack, inserted - insertedExternally, false, false); } return remainder; } @Override @Nonnull public ItemStack extractItem(@Nonnull ItemStack stack, int size, int flags, Action action, Predicate> filter) { if (stack.isEmpty()) { return stack; } int requested = size; int received = 0; int extractedExternally = 0; ItemStack newStack = ItemStack.EMPTY; for (IStorage storage : this.itemStorage.getStorages()) { ItemStack took = ItemStack.EMPTY; if (filter.test(storage) && storage.getAccessType() != AccessType.INSERT) { took = storage.extract(stack, requested - received, flags, action); } if (!took.isEmpty()) { // The external storage is responsible for sending changes, we don't need to anymore if (storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); extractedExternally += took.getCount(); } if (newStack.isEmpty()) { newStack = took; } else { newStack.grow(took.getCount()); } received += took.getCount(); } if (requested == received) { break; } } if (newStack.getCount() - extractedExternally > 0 && action == Action.PERFORM) { itemStorage.remove(newStack, newStack.getCount() - extractedExternally, false); } return newStack; } @Override @Nonnull public FluidStack insertFluid(@Nonnull FluidStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } if (fluidStorage.getStorages().isEmpty()) { return StackUtils.copy(stack, size); } FluidStack remainder = StackUtils.copy(stack, size); int inserted = 0; int insertedExternally = 0; for (IStorage storage : this.fluidStorage.getStorages()) { if (storage.getAccessType() == AccessType.EXTRACT) { continue; } int storedPre = storage.getStored(); remainder = storage.insert(remainder, size, action); if (action == Action.PERFORM) { inserted += storage.getCacheDelta(storedPre, size, remainder); } if (remainder.isEmpty()) { // The external storage is responsible for sending changes, we don't need to anymore if (storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); insertedExternally += size; } break; } else { // The external storage is responsible for sending changes, we don't need to anymore if (size != remainder.getAmount() && storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); insertedExternally += size - remainder.getAmount(); } size = remainder.getAmount(); } } if (action == Action.PERFORM && inserted - insertedExternally > 0) { fluidStorage.add(stack, inserted - insertedExternally, false, false); } return remainder; } @Override @Nonnull public FluidStack extractFluid(@Nonnull FluidStack stack, int size, int flags, Action action, Predicate> filter) { if (stack.isEmpty()) { return stack; } int requested = size; int received = 0; int extractedExternally = 0; FluidStack newStack = FluidStack.EMPTY; for (IStorage storage : this.fluidStorage.getStorages()) { FluidStack took = FluidStack.EMPTY; if (filter.test(storage) && storage.getAccessType() != AccessType.INSERT) { took = storage.extract(stack, requested - received, flags, action); } if (!took.isEmpty()) { // The external storage is responsible for sending changes, we don't need to anymore if (storage instanceof IExternalStorage && action == Action.PERFORM) { ((IExternalStorage) storage).update(this); extractedExternally += took.getAmount(); } if (newStack.isEmpty()) { newStack = took; } else { newStack.grow(took.getAmount()); } received += took.getAmount(); } if (requested == received) { break; } } if (newStack.getAmount() - extractedExternally > 0 && action == Action.PERFORM) { fluidStorage.remove(newStack, newStack.getAmount() - extractedExternally, false); } return newStack; } @Override public IStorageTracker getItemStorageTracker() { if (itemStorageTracker == null) { if (itemStorageTrackerId == null) { this.itemStorageTrackerId = UUID.randomUUID(); } this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) level).getOrCreate(itemStorageTrackerId, StorageType.ITEM); } return itemStorageTracker; } @Override public IStorageTracker getFluidStorageTracker() { if (fluidStorageTracker == null) { if (fluidStorageTrackerId == null) { this.fluidStorageTrackerId = UUID.randomUUID(); } this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) level).getOrCreate(fluidStorageTrackerId, StorageType.FLUID); } return fluidStorageTracker; } @Override public Level getLevel() { return level; } @Override public INetwork readFromNbt(CompoundTag tag) { if (tag.contains(NBT_ENERGY)) { this.energy.setStored(tag.getInt(NBT_ENERGY)); } redstoneMode = RedstoneMode.read(tag); craftingManager.readFromNbt(tag); if (tag.contains(NBT_ITEM_STORAGE_TRACKER_ID)) { this.itemStorageTrackerId = tag.getUUID(NBT_ITEM_STORAGE_TRACKER_ID); } if (tag.contains(NBT_FLUID_STORAGE_TRACKER_ID)) { this.fluidStorageTrackerId = tag.getUUID(NBT_FLUID_STORAGE_TRACKER_ID); } return this; } @Override public CompoundTag writeToNbt(CompoundTag tag) { tag.putInt(NBT_ENERGY, this.energy.getEnergyStored()); redstoneMode.write(tag); craftingManager.writeToNbt(tag); if (itemStorageTrackerId != null) { tag.putUUID(NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId); } if (fluidStorageTrackerId != null) { tag.putUUID(NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId); } return tag; } @Override public long[] getTickTimes() { return tickTimes; } @Override public void markDirty() { API.instance().getNetworkManager((ServerLevel) level).markForSaving(); } public ControllerBlock.EnergyType getEnergyType() { if (!redstoneMode.isEnabled(redstonePowered)) { return ControllerBlock.EnergyType.OFF; } return getEnergyType(this.energy.getEnergyStored(), this.energy.getMaxEnergyStored()); } @Override public RedstoneMode getRedstoneMode() { return redstoneMode; } @Override public void setRedstoneMode(RedstoneMode mode) { this.redstoneMode = mode; markDirty(); } private void updateEnergyUsage() { if (!redstoneMode.isEnabled(redstonePowered)) { this.lastEnergyUsage = 0; return; } int usage = RS.SERVER_CONFIG.getController().getBaseUsage(); for (INetworkNodeGraphEntry entry : nodeGraph.all()) { if (entry.getNode().isActive()) { usage += entry.getNode().getEnergyUsage(); } } this.lastEnergyUsage = usage; } @Override public int getEnergyUsage() { return lastEnergyUsage; } @Override public IEnergyStorage getEnergyStorage() { return energy; } @Override public NetworkType getType() { return type; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.server.level.ServerLevel; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.event.TickEvent; public class NetworkListener { @SubscribeEvent public void onLevelTick(TickEvent.LevelTickEvent e) { if (!e.level.isClientSide() && e.phase == TickEvent.Phase.END) { e.level.getProfiler().push("network ticking"); for (INetwork network : API.instance().getNetworkManager((ServerLevel) e.level).all()) { network.update(); } e.level.getProfiler().pop(); e.level.getProfiler().push("network node ticking"); for (INetworkNode node : API.instance().getNetworkNodeManager((ServerLevel) e.level).all()) { node.update(); } e.level.getProfiler().pop(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.apiimpl.util.RSSavedData; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.world.level.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; public class NetworkManager extends RSSavedData implements INetworkManager { public static final String NAME = "refinedstorage_networks"; private static final String NBT_NETWORKS = "Networks"; private static final String NBT_TYPE = "Type"; private static final String NBT_DATA = "Data"; private static final String NBT_POS = "Pos"; private final Level level; private final Logger logger = LogManager.getLogger(getClass()); private final ConcurrentHashMap networks = new ConcurrentHashMap<>(); public NetworkManager(Level level) { this.level = level; } @Override public void load(CompoundTag tag) { if (tag.contains(NBT_NETWORKS)) { ListTag networksTag = tag.getList(NBT_NETWORKS, Tag.TAG_COMPOUND); this.networks.clear(); for (int i = 0; i < networksTag.size(); ++i) { CompoundTag networkTag = networksTag.getCompound(i); CompoundTag data = networkTag.getCompound(NBT_DATA); BlockPos pos = BlockPos.of(networkTag.getLong(NBT_POS)); int type = networkTag.getInt(NBT_TYPE); INetwork network = new Network(level, pos, NetworkType.values()[type]); try { network = network.readFromNbt(data); } catch (Throwable t) { logger.error("Error while reading network", t); } this.networks.put(pos, network); } } } @Override public CompoundTag save(CompoundTag tag) { ListTag list = new ListTag(); for (INetwork network : all()) { try { CompoundTag networkTag = new CompoundTag(); networkTag.putLong(NBT_POS, network.getPosition().asLong()); networkTag.put(NBT_DATA, network.writeToNbt(new CompoundTag())); networkTag.putInt(NBT_TYPE, network.getType().ordinal()); list.add(networkTag); } catch (Throwable t) { logger.error("Error while saving network", t); } } tag.put(NBT_NETWORKS, list); return tag; } @Nullable @Override public INetwork getNetwork(BlockPos pos) { return networks.get(pos); } @Override public void removeNetwork(BlockPos pos) { if (pos == null) { throw new IllegalArgumentException("Position cannot be null"); } networks.remove(pos); } @Override public void setNetwork(BlockPos pos, INetwork network) { if (pos == null) { throw new IllegalArgumentException("Position cannot be null"); } if (network == null) { throw new IllegalArgumentException("Network cannot be null"); } networks.put(pos, network); } @Override public Collection all() { return networks.values(); } @Override public void markForSaving() { setDirty(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeGraph.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.google.common.collect.Sets; import com.refinedmods.refinedstorage.api.network.*; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; import java.util.*; import java.util.function.Consumer; public class NetworkNodeGraph implements INetworkNodeGraph { private final INetwork network; private final List listeners = new LinkedList<>(); private final Set> actions = new HashSet<>(); private Set entries = Sets.newConcurrentHashSet(); private boolean invalidating = false; public NetworkNodeGraph(INetwork network) { this.network = network; } @Override public void invalidate(Action action, Level level, BlockPos origin) { this.invalidating = true; Operator operator = new Operator(action); INetworkNode originNode = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(origin)); if (originNode instanceof INetworkNodeVisitor) { ((INetworkNodeVisitor) originNode).visit(operator); } Visitor currentVisitor; while ((currentVisitor = operator.toCheck.poll()) != null) { currentVisitor.visit(operator); } this.entries = operator.foundNodes; if (action == Action.PERFORM) { for (INetworkNodeGraphEntry entry : operator.newEntries) { entry.getNode().onConnected(network); } for (INetworkNodeGraphEntry entry : operator.previousEntries) { entry.getNode().onDisconnected(network); } actions.forEach(h -> h.accept(network)); actions.clear(); if (!operator.newEntries.isEmpty() || !operator.previousEntries.isEmpty()) { listeners.forEach(INetworkNodeGraphListener::onChanged); } } this.invalidating = false; } @Override public void runActionWhenPossible(Consumer handler) { if (invalidating) { actions.add(handler); } else { handler.accept(network); } } @Override public Collection all() { return entries; } @Override public void addListener(INetworkNodeGraphListener listener) { listeners.add(listener); } @Override public void disconnectAll() { entries.forEach(entry -> entry.getNode().onDisconnected(network)); entries.clear(); listeners.forEach(INetworkNodeGraphListener::onChanged); } protected Level getLevel() { return network.getLevel(); } private static class Visitor implements INetworkNodeVisitor { private final INetworkNode node; private final Level level; private final BlockPos pos; private final Direction side; private final BlockEntity blockEntity; Visitor(INetworkNode node, Level level, BlockPos pos, Direction side, BlockEntity blockEntity) { this.node = node; this.level = level; this.pos = pos; this.side = side; this.blockEntity = blockEntity; } @Override public void visit(com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor.Operator operator) { if (node instanceof INetworkNodeVisitor) { ((INetworkNodeVisitor) node).visit(operator); } else { for (Direction checkSide : Direction.values()) { if (checkSide != side) { // Avoid going backward INetworkNode nodeOnSide = NetworkUtils.getNodeFromBlockEntity(blockEntity); if (nodeOnSide == node) { BlockPos relativePos = pos.relative(checkSide); if (level.isLoaded(relativePos)) { operator.apply(level, relativePos, checkSide.getOpposite()); } } } } } } } private class Operator implements INetworkNodeVisitor.Operator { private final Set foundNodes = Sets.newConcurrentHashSet(); // All scanned entries private final Set newEntries = Sets.newConcurrentHashSet(); // All scanned new entries, that didn't appear in the list before private final Set previousEntries = Sets.newConcurrentHashSet(entries); // All unscanned entries (entries that were in the previous list, but not in the new list) private final Queue toCheck = new ArrayDeque<>(); private final Action action; public Operator(Action action) { this.action = action; } @Override public void apply(Level level, BlockPos pos, @Nullable Direction side) { BlockEntity blockEntity = level.getBlockEntity(pos); INetworkNode otherNode = NetworkUtils.getNodeFromBlockEntity(blockEntity); if (otherNode != null) { NetworkNodeGraphEntry otherNodeItem = new NetworkNodeGraphEntry(otherNode); if (otherNode.getNetwork() != null && !otherNode.getNetwork().equals(network)) { if (action == Action.PERFORM) { dropConflictingBlock(level, pos); } return; } if (foundNodes.add(otherNodeItem)) { if (!entries.contains(otherNodeItem)) { // We can't let the node connect immediately // We can only let the node connect AFTER the nodes list has changed in the graph // This is so that storage nodes can refresh the item/fluid cache, and the item/fluid cache will notice it then (otherwise not) newEntries.add(otherNodeItem); } previousEntries.remove(otherNodeItem); toCheck.add(new Visitor(otherNode, level, pos, side, blockEntity)); } } } private void dropConflictingBlock(Level level, BlockPos pos) { if (!network.getPosition().equals(pos)) { Block.dropResources(level.getBlockState(pos), level, pos, level.getBlockEntity(pos)); level.removeBlock(pos, false); } } @Override public Action getAction() { return action; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeGraphEntry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; public class NetworkNodeGraphEntry implements INetworkNodeGraphEntry { private final INetworkNode node; public NetworkNodeGraphEntry(INetworkNode node) { this.node = node; } @Override public INetworkNode getNode() { return node; } @Override public boolean equals(Object other) { if (!(other instanceof NetworkNodeGraphEntry)) { return false; } if (this == other) { return true; } NetworkNodeGraphEntry otherItem = (NetworkNodeGraphEntry) other; if (node.getLevel().dimension() != otherItem.node.getLevel().dimension()) { return false; } return node.getPos().equals(otherItem.node.getPos()); } @Override public int hashCode() { int result = node.getPos().hashCode(); result = 31 * result + node.getLevel().dimension().hashCode(); return result; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.PlayerUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.LevelAccessor; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.event.level.BlockEvent; public class NetworkNodeListener { @SubscribeEvent public void onBlockPlace(BlockEvent.EntityPlaceEvent e) { if (!e.getLevel().isClientSide() && e.getEntity() instanceof Player) { Player player = (Player) e.getEntity(); INetworkNode placed = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getPos())); if (placed != null) { for (Direction facing : Direction.values()) { INetworkNode node = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getBlockSnapshot().getPos().relative(facing))); if (node != null && node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, player)) { LevelUtils.sendNoPermissionMessage(player); e.setCanceled(true); //Fixes desync as we do not cancel the event clientside PlayerUtils.updateHeldItems((ServerPlayer) player); return; } } discoverNode(e.getLevel(), e.getPos()); placed.setOwner(player.getGameProfile().getId()); } } } private void discoverNode(LevelAccessor world, BlockPos pos) { for (Direction facing : Direction.values()) { INetworkNode node = NetworkUtils.getNodeFromBlockEntity(world.getBlockEntity(pos.relative(facing))); if (node != null && node.getNetwork() != null) { node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition()); return; } } } @SubscribeEvent public void onBlockBreak(BlockEvent.BreakEvent e) { if (!e.getLevel().isClientSide()) { INetworkNode node = NetworkUtils.getNodeFromBlockEntity(e.getLevel().getBlockEntity(e.getPos())); if (node != null && node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, e.getPlayer())) { LevelUtils.sendNoPermissionMessage(e.getPlayer()); e.setCanceled(true); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeFactory; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.util.RSSavedData; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.Collection; import java.util.concurrent.ConcurrentHashMap; public class NetworkNodeManager extends RSSavedData implements INetworkNodeManager { public static final String NAME = "refinedstorage_nodes"; private static final String NBT_NODES = "Nodes"; private static final String NBT_NODE_ID = "Id"; private static final String NBT_NODE_DATA = "Data"; private static final String NBT_NODE_POS = "Pos"; private final Level level; private final Logger logger = LogManager.getLogger(getClass()); private final ConcurrentHashMap nodes = new ConcurrentHashMap<>(); public NetworkNodeManager(Level level) { this.level = level; } @Override public void load(CompoundTag tag) { if (tag.contains(NBT_NODES)) { ListTag nodesTag = tag.getList(NBT_NODES, Tag.TAG_COMPOUND); this.nodes.clear(); for (int i = 0; i < nodesTag.size(); ++i) { CompoundTag nodeTag = nodesTag.getCompound(i); ResourceLocation id = new ResourceLocation(nodeTag.getString(NBT_NODE_ID)); CompoundTag data = nodeTag.getCompound(NBT_NODE_DATA); BlockPos pos = BlockPos.of(nodeTag.getLong(NBT_NODE_POS)); INetworkNodeFactory factory = API.instance().getNetworkNodeRegistry().get(id); if (factory != null) { INetworkNode node = null; try { node = factory.create(data, level, pos); } catch (Throwable t) { logger.error("Could not read network node", t); } if (node != null) { this.nodes.put(pos, node); } } else { logger.warn("Factory for {} not found in network node registry", id); } } } } @Override public CompoundTag save(CompoundTag tag) { ListTag list = new ListTag(); for (INetworkNode node : all()) { try { CompoundTag nodeTag = new CompoundTag(); nodeTag.putString(NBT_NODE_ID, node.getId().toString()); nodeTag.putLong(NBT_NODE_POS, node.getPos().asLong()); nodeTag.put(NBT_NODE_DATA, node.write(new CompoundTag())); list.add(nodeTag); } catch (Throwable t) { logger.error("Error while saving network node", t); } } tag.put(NBT_NODES, list); return tag; } @Nullable @Override public INetworkNode getNode(BlockPos pos) { return nodes.get(pos); } @Override public void removeNode(BlockPos pos) { if (pos == null) { throw new IllegalArgumentException("Position cannot be null"); } nodes.remove(pos); } @Override public void setNode(BlockPos pos, INetworkNode node) { if (pos == null) { throw new IllegalArgumentException("Position cannot be null"); } if (node == null) { throw new IllegalArgumentException("Node cannot be null"); } nodes.put(pos, node); } @Override public Collection all() { return nodes.values(); } @Override public void markForSaving() { setDirty(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/NetworkNodeRegistry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeFactory; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeRegistry; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class NetworkNodeRegistry implements INetworkNodeRegistry { private final Map factories = new HashMap<>(); @Override public void add(ResourceLocation id, INetworkNodeFactory factory) { factories.put(id, factory); } @Override @Nullable public INetworkNodeFactory get(ResourceLocation id) { return factories.get(id); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/CraftingGridBehavior.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridBehavior; import com.refinedmods.refinedstorage.api.network.grid.INetworkAwareGrid; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.item.PatternItem; import net.minecraft.core.NonNullList; import net.minecraft.world.Containers; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.event.EventHooks; import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.wrapper.PlayerMainInvWrapper; import javax.annotation.Nullable; import java.util.*; import java.util.concurrent.atomic.AtomicReference; public class CraftingGridBehavior implements ICraftingGridBehavior { @Override public void onCrafted(INetworkAwareGrid grid, CraftingRecipe recipe, Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { NonNullList remainder = recipe.getRemainingItems(grid.getCraftingMatrix()); INetwork network = grid.getNetwork(); CraftingContainer matrix = grid.getCraftingMatrix(); for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) { ItemStack slot = matrix.getItem(i); // Do we have a remainder? if (i < remainder.size() && !remainder.get(i).isEmpty()) { // If there is no space for the remainder, dump it in the player inventory. if (!slot.isEmpty() && slot.getCount() > 1) { if (!player.getInventory().add(remainder.get(i).copy())) { // If there is no space in the player inventory, try to dump it in the network. ItemStack remainderStack = network == null ? remainder.get(i).copy() : network.insertItem(remainder.get(i).copy(), remainder.get(i).getCount(), Action.PERFORM); // If there is no space in the network, just dump it in the world. if (!remainderStack.isEmpty()) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), remainderStack); } } matrix.removeItem(i, 1); } else { matrix.setItem(i, remainder.get(i).copy()); } } else if (!slot.isEmpty()) { // We don't have a remainder, but the slot is not empty. 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. ItemStack refill; if (availableItems == null) { // for regular crafting refill = network.extractItem(slot, 1, Action.PERFORM); } else { // for shift crafting if (availableItems.get(slot) != null) { refill = availableItems.remove(slot, 1).getStack().copy(); refill.setCount(1); usedItems.add(refill); } else { refill = ItemStack.EMPTY; } } matrix.setItem(i, refill); if (!refill.isEmpty()) { network.getItemStorageTracker().changed(player, refill.copy()); } } else { // We don't have a network, or, the slot still has more than 1 items in it. Just decrement then. matrix.removeItem(i, 1); } } } grid.onCraftingMatrixChanged(); } @Override public void onCraftedShift(INetworkAwareGrid grid, Player player) { CraftingContainer matrix = grid.getCraftingMatrix(); INetwork network = grid.getNetwork(); List craftedItemsList = new ArrayList<>(); ItemStack crafted = grid.getCraftingResult().getItem(0); int maxCrafted = crafted.getMaxStackSize(); int amountCrafted = 0; boolean useNetwork = network != null && grid.isGridActive(); IStackList availableItems = API.instance().createItemStackList(); if (useNetwork) { // We need a modifiable list of the items in storage that are relevant for this craft. // For performance reason we extract these into an extra list filterDuplicateStacks(network, matrix, availableItems); } //A second list to remember which items have been extracted IStackList usedItems = API.instance().createItemStackList(); CommonHooks.setCraftingPlayer(player); // 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. do { grid.onCrafted(player, availableItems, usedItems); craftedItemsList.add(crafted.copy()); amountCrafted += crafted.getCount(); } while (API.instance().getComparer().isEqual(crafted, grid.getCraftingResult().getItem(0)) && amountCrafted < maxCrafted && amountCrafted + crafted.getCount() <= maxCrafted); if (useNetwork) { usedItems.getStacks().forEach(stack -> network.extractItem(stack.getStack(), stack.getStack().getCount(), Action.PERFORM)); } for (ItemStack craftedItem : craftedItemsList) { ItemStack remainder = ItemHandlerHelper.insertItem( new PlayerMainInvWrapper(player.getInventory()), craftedItem.copy(), false ); if (!remainder.isEmpty() && useNetwork) { remainder = network.insertItem(remainder, remainder.getCount(), Action.PERFORM); } if (!remainder.isEmpty()) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), remainder); } } // @Volatile: This is some logic copied from ResultSlot#checkTakeAchievements. We call this manually for shift clicking because // otherwise it's not being called. // For regular crafting, this is already called in ResultCraftingGridSlot#onTake -> checkTakeAchievements(stack) crafted.onCraftedBy(player.level(), player, amountCrafted); EventHooks.firePlayerCraftingEvent(player, ItemHandlerHelper.copyStackWithSize(crafted, amountCrafted), grid.getCraftingMatrix()); CommonHooks.setCraftingPlayer(null); } private void filterDuplicateStacks(INetwork network, CraftingContainer matrix, IStackList availableItems) { for (int i = 0; i < matrix.getContainerSize(); ++i) { ItemStack stack = network.getItemStorageCache().getList().get(matrix.getItem(i)); //Don't add the same item twice into the list. Items may appear twice in a recipe but not in storage. if (stack != null && availableItems.get(stack) == null) { availableItems.add(stack); } } } @Override public void onRecipeTransfer(INetworkAwareGrid grid, Player player, ItemStack[][] recipe) { INetwork network = grid.getNetwork(); if (network != null && grid.getGridType() == GridType.CRAFTING && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) { return; } // First try to empty the crafting matrix for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) { ItemStack slot = grid.getCraftingMatrix().getItem(i); if (!slot.isEmpty()) { // Only if we are a crafting grid. Pattern grids can just be emptied. if (grid.getGridType() == GridType.CRAFTING) { // If we are connected, try to insert into network. If it fails, stop. if (network != null && grid.isGridActive()) { if (!network.insertItem(slot, slot.getCount(), Action.SIMULATE).isEmpty()) { return; } else { network.insertItem(slot, slot.getCount(), Action.PERFORM); network.getItemStorageTracker().changed(player, slot.copy()); } } else { // If we aren't connected, try to insert into player inventory. If it fails, stop. if (!player.getInventory().add(slot.copy())) { return; } } } grid.getCraftingMatrix().setItem(i, ItemStack.EMPTY); } } AtomicReference> playerItems = new AtomicReference<>(); // Now let's fill the matrix for (int i = 0; i < grid.getCraftingMatrix().getContainerSize(); ++i) { if (recipe[i] != null) { ItemStack[] possibilities = recipe[i]; if (network != null && grid.isGridActive() && network.getItemStorageCache() != null) { // sort by the number of items in storage, craftables and inventory Arrays.sort(possibilities, compareByItemStackCounts(player, network, playerItems)); } // If we are a crafting grid if (grid.getGridType() == GridType.CRAFTING) { boolean found = false; // If we are connected, first try to get the possibilities from the network if (network != null && grid.isGridActive()) { for (ItemStack possibility : possibilities) { ItemStack took = network.extractItem(possibility, possibility.getCount(), IComparer.COMPARE_NBT, Action.PERFORM); if (!took.isEmpty()) { grid.getCraftingMatrix().setItem(i, took); network.getItemStorageTracker().changed(player, took.copy()); found = true; break; } } } // If we haven't found anything in the network (or we are disconnected), go look in the player inventory if (!found) { for (ItemStack possibility : possibilities) { for (int j = 0; j < player.getInventory().getContainerSize(); ++j) { if (API.instance().getComparer().isEqual(possibility, player.getInventory().getItem(j), IComparer.COMPARE_NBT)) { grid.getCraftingMatrix().setItem(i, ItemHandlerHelper.copyStackWithSize(player.getInventory().getItem(j), 1)); player.getInventory().removeItem(j, 1); found = true; break; } } if (found) { break; } } } } else if (grid.getGridType() == GridType.PATTERN) { // If we are a pattern grid we can just set the slot grid.getCraftingMatrix().setItem(i, possibilities.length == 0 ? ItemStack.EMPTY : possibilities[0]); } } } if (grid.getGridType() == GridType.PATTERN) { ((GridNetworkNode) grid).setProcessingPattern(false); ((GridNetworkNode) grid).markDirty(); } } private Comparator compareByItemStackCounts(Player player, INetwork network, AtomicReference> playerItems) { return Comparator.comparingInt((ItemStack itemStack) -> { ItemStack stack = network.getItemStorageCache().getList().get(itemStack); if (stack != null) { return stack.getCount(); } if (network.getCraftingManager().getPattern(itemStack) != null) { return 1; } if (playerItems.get() == null) { playerItems.set(makePlayerInventoryMap(player, network)); } ItemStack onPlayer = playerItems.get().get(itemStack.getItem()); if (onPlayer != null) { return onPlayer.getCount(); } return 0; }).reversed(); } private Map makePlayerInventoryMap(Player player, INetwork network) { Map playerItems = new HashMap<>(); for (int j = 0; j < player.getInventory().getContainerSize(); j++) { ItemStack inventoryStack = player.getInventory().getItem(j); if (inventoryStack.getItem() instanceof ICraftingPatternProvider) { ICraftingPattern pattern = PatternItem.fromCache(network.getLevel(), inventoryStack); if (pattern.isValid()) { for (ItemStack stack : pattern.getOutputs()) { if (!stack.isEmpty()) { playerItems.put(stack.getItem(), stack); } } } } else { playerItems.put(inventoryStack.getItem(), inventoryStack); } } return playerItems; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/GridManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.api.network.grid.IGridManager; import com.refinedmods.refinedstorage.container.factory.GridMenuProvider; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class GridManager implements IGridManager { private final Map factories = new HashMap<>(); @Override public void add(ResourceLocation id, IGridFactory factory) { factories.put(id, factory); } @Override public void openGrid(ResourceLocation id, ServerPlayer player, BlockPos pos) { openGrid(id, player, null, pos, new PlayerSlot(-1)); } @Override public void openGrid(ResourceLocation id, ServerPlayer player, ItemStack stack, PlayerSlot slot) { openGrid(id, player, stack, null, slot); } private void openGrid(ResourceLocation id, ServerPlayer player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot) { Pair grid = createGrid(id, player, stack, pos, slot); if (grid == null) { return; } player.openMenu(new GridMenuProvider(grid.getLeft(), grid.getRight()), buf -> { buf.writeResourceLocation(id); buf.writeBoolean(pos != null); if (pos != null) { buf.writeBlockPos(pos); } buf.writeBoolean(stack != null); if (stack != null) { buf.writeItem(stack); } slot.writePlayerSlot(buf); }); } @Override @Nullable public Pair createGrid(ResourceLocation id, Player player, @Nullable ItemStack stack, @Nullable BlockPos pos, PlayerSlot slot) { IGridFactory factory = factories.get(id); if (factory == null) { return null; } IGrid grid = null; BlockEntity blockEntity = factory.getRelevantBlockEntity(player.level(), pos); if (factory.getType() == GridFactoryType.STACK) { grid = factory.createFromStack(player, stack, slot); } else if (factory.getType() == GridFactoryType.BLOCK) { grid = factory.createFromBlock(player, pos); } if (grid == null) { return null; } return Pair.of(grid, blockEntity); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/GridTab.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid; import com.mojang.blaze3d.platform.Lighting; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.api.util.IFilter; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; public class GridTab implements IGridTab { private final List filters; @Nullable private final MutableComponent name; @Nonnull private final ItemStack icon; @Nullable private final FluidStack fluidIcon; public GridTab(List filters, String name, @Nonnull ItemStack icon, @Nullable FluidStack fluidIcon) { this.filters = filters; this.name = name.trim().isEmpty() ? null : Component.literal(name); this.icon = icon; this.fluidIcon = fluidIcon; } @Override public List getFilters() { return filters; } @Override public void drawTooltip(Font font, GuiGraphics graphics, int x, int y) { if (name != null) { graphics.renderTooltip(font, name, x, y); } } @Override public void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer) { if (!icon.isEmpty()) { Lighting.setupFor3DItems(); itemDrawer.draw(graphics, x, y, icon); } else { fluidDrawer.draw(graphics, x, y, fluidIcon); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/GridBlockGridFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class GridBlockGridFactory implements IGridFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid"); @Override @Nullable public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) { return null; } @Override @Nullable public IGrid createFromBlock(Player player, BlockPos pos) { BlockEntity blockEntity = getRelevantBlockEntity(player.getCommandSenderWorld(), pos); if (blockEntity instanceof GridBlockEntity) { return ((GridBlockEntity) blockEntity).getNode(); } return null; } @Nullable @Override public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) { return level.getBlockEntity(pos); } @Override public GridFactoryType getType() { return GridFactoryType.BLOCK; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/PortableGridBlockGridFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class PortableGridBlockGridFactory implements IGridFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "portable_grid_block"); @Override @Nullable public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) { return null; } @Override @Nullable public IGrid createFromBlock(Player player, BlockPos pos) { BlockEntity blockEntity = getRelevantBlockEntity(player.level(), pos); if (blockEntity instanceof PortableGridBlockEntity) { return (PortableGridBlockEntity) blockEntity; } return null; } @Nullable @Override public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) { return level.getBlockEntity(pos); } @Override public GridFactoryType getType() { return GridFactoryType.BLOCK; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/PortableGridGridFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class PortableGridGridFactory implements IGridFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "portable_grid_item"); @Nullable @Override public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) { PortableGrid portableGrid = new PortableGrid(player, stack, slot); portableGrid.onOpen(); return portableGrid; } @Nullable @Override public IGrid createFromBlock(Player player, BlockPos pos) { return null; } @Nullable @Override public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) { return null; } @Override public GridFactoryType getType() { return GridFactoryType.STACK; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/WirelessFluidGridGridFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.WirelessFluidGrid; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class WirelessFluidGridGridFactory implements IGridFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_fluid_grid"); @Nullable @Override public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) { return new WirelessFluidGrid(stack, player.getServer(), slot); } @Nullable @Override public IGrid createFromBlock(Player player, BlockPos pos) { return null; } @Nullable @Override public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) { return null; } @Override public GridFactoryType getType() { return GridFactoryType.STACK; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/factory/WirelessGridGridFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridFactoryType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.WirelessGrid; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class WirelessGridGridFactory implements IGridFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_grid"); @Nullable @Override public IGrid createFromStack(Player player, ItemStack stack, PlayerSlot slot) { return new WirelessGrid(stack, player.getServer(), slot); } @Nullable @Override public IGrid createFromBlock(Player player, BlockPos pos) { return null; } @Nullable @Override public BlockEntity getRelevantBlockEntity(Level level, BlockPos pos) { return null; } @Override public GridFactoryType getType() { return GridFactoryType.STACK; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/FluidGridHandler.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.handler; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Containers; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; import java.util.Collections; import java.util.UUID; public class FluidGridHandler implements IFluidGridHandler { private final INetwork network; public FluidGridHandler(INetwork network) { this.network = network; } @Override public void onExtract(ServerPlayer player, UUID id, boolean shift) { FluidStack stack = network.getFluidStorageCache().getList().get(id); if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME || !network.getSecurityManager().hasPermission(Permission.EXTRACT, player) || !network.canRun()) { return; } NetworkUtils.extractBucketFromPlayerInventoryOrNetwork(player, network, bucket -> { IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM); if (fluidHandler != null) { network.getFluidStorageTracker().changed(player, stack.copy()); FluidStack extracted = network.extractFluid(stack, FluidType.BUCKET_VOLUME, Action.PERFORM); fluidHandler.fill(extracted, IFluidHandler.FluidAction.EXECUTE); if (shift) { if (!player.getInventory().add(fluidHandler.getContainer().copy())) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), fluidHandler.getContainer()); } } else { player.containerMenu.setCarried(fluidHandler.getContainer()); } network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessFluidGrid().getExtractUsage()); } }); } @Override @Nonnull public ItemStack onInsert(ServerPlayer player, ItemStack container) { if (!network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) { return container; } Pair result = StackUtils.getFluid(container, true); if (!result.getValue().isEmpty() && network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) { network.getFluidStorageTracker().changed(player, result.getValue().copy()); result = StackUtils.getFluid(container, false); network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.PERFORM); network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessFluidGrid().getInsertUsage()); return result.getLeft(); } return container; } @Override public void onInsertHeldContainer(ServerPlayer player) { player.containerMenu.setCarried(onInsert(player, player.containerMenu.getCarried())); } @Override public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) { if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { return; } FluidStack stack = network.getFluidStorageCache().getCraftablesList().get(id); if (stack != null) { ICalculationResult result = network.getCraftingManager().create(stack, quantity); if (result == null) { return; } if (!result.isOk() && result.getType() != CalculationResultType.MISSING) { RS.NETWORK_HANDLER.sendTo( player, new GridCraftingPreviewResponseMessage( Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())), id, quantity, true ) ); } else if (result.isOk() && noPreview) { network.getCraftingManager().start(result.getTask()); RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage()); } else { RS.NETWORK_HANDLER.sendTo( player, new GridCraftingPreviewResponseMessage( result.getPreviewElements(), id, quantity, true ) ); } } } @Override public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) { if (quantity <= 0 || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { return; } FluidStack stack = network.getFluidStorageCache().getCraftablesList().get(id); if (stack != null) { ICalculationResult result = network.getCraftingManager().create(stack, quantity); if (result.isOk()) { network.getCraftingManager().start(result.getTask()); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/ItemGridHandler.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.handler; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.task.CalculationResultType; import com.refinedmods.refinedstorage.api.autocrafting.task.ICalculationResult; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collections; import java.util.Optional; import java.util.UUID; public class ItemGridHandler implements IItemGridHandler { private final INetwork network; public ItemGridHandler(INetwork network) { this.network = network; } public static void onInventoryScroll(IItemGridHandler gridHandler, ServerPlayer player, int slot, boolean shift, boolean up, @Nullable INetwork network) { if (player == null || !(player.containerMenu instanceof GridContainerMenu)) { return; } if (network != null && ((up && !network.getSecurityManager().hasPermission(Permission.INSERT, player)) || (!up && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)))) { return; } int flags = EXTRACT_SINGLE; ItemStack stackInSlot = player.getInventory().getItem(slot); ItemStack stackOnCursor = player.containerMenu.getCarried(); if (shift) { // shift flags |= EXTRACT_SHIFT; if (!stackInSlot.isEmpty()) { if (up) { // scroll up player.getInventory().setItem(slot, gridHandler.onInsert(player, stackInSlot, true)); } else { // scroll down gridHandler.onExtract(player, stackInSlot, slot, flags); } } } else { //ctrl if (up) { // scroll up if (!stackOnCursor.isEmpty()) { gridHandler.onInsert(player, stackOnCursor, true); } } else { //scroll down if (stackOnCursor.isEmpty()) { gridHandler.onExtract(player, stackInSlot, -1, flags); } else { gridHandler.onExtract(player, stackOnCursor, -1, flags); } } } } public static void onGridScroll(IItemGridHandler gridHandler, ServerPlayer player, @Nullable UUID id, boolean shift, boolean up, @Nullable INetwork network) { if (player == null || !(player.containerMenu instanceof GridContainerMenu)) { return; } if (network != null && ((up && !network.getSecurityManager().hasPermission(Permission.INSERT, player)) || (!up && !network.getSecurityManager().hasPermission(Permission.EXTRACT, player)))) { return; } IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); int flags = EXTRACT_SINGLE; if (shift && id != null) { flags |= EXTRACT_SHIFT; if (up) { //scroll up, insert hovering stack pulled from Inventory IStorageCache cache = grid.getStorageCache(); if (cache == null || cache.getList().get(id) == null) { return; } for (int i = 0; i < player.getInventory().items.size(); i++) { if (API.instance().getComparer().isEqual(player.getInventory().getItem(i), cache.getList().get(id), IComparer.COMPARE_NBT)) { gridHandler.onInsert(player, player.getInventory().getItem(i), true); break; } } } else { //scroll down, extract hovering item gridHandler.onExtract(player, id, -1, flags); } } else { //ctrl if (!up && id != null) { //scroll down, extract hovering item gridHandler.onExtract(player, id, -1, flags); } else if (up && !player.containerMenu.getCarried().isEmpty()) { // insert stack from cursor gridHandler.onInsert(player, player.containerMenu.getCarried(), true); } } } @Override public void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags) { StackListEntry stackEntry = network.getItemStorageCache().getList().getEntry(stack, IComparer.COMPARE_NBT); if (stackEntry != null) { onExtract(player, stackEntry.getId(), preferredSlot, flags); } } @Override public void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags) { ItemStack item = network.getItemStorageCache().getList().get(id); if (item == null || !network.getSecurityManager().hasPermission(Permission.EXTRACT, player) || !network.canRun()) { return; } int itemSize = item.getCount(); // We copy here because some mods change the NBT tag of an item after getting the stack limit int maxItemSize = item.getItem().getMaxStackSize(item.copy()); boolean single = (flags & EXTRACT_SINGLE) == EXTRACT_SINGLE; ItemStack held = player.containerMenu.getCarried(); if (single) { if (!held.isEmpty() && (!API.instance().getComparer().isEqualNoQuantity(item, held) || held.getCount() + 1 > held.getMaxStackSize())) { return; } } else if (!player.containerMenu.getCarried().isEmpty()) { return; } int size = 64; if ((flags & EXTRACT_HALF) == EXTRACT_HALF && itemSize > 1) { size = itemSize / 2; // Rationale for this check: // If we have 32 buckets, and we want to extract half, we expect/need to get 8 (max stack size 16 / 2). // Without this check, we would get 16 (total stack size 32 / 2). // 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). if (size > maxItemSize / 2 && maxItemSize != 1) { size = maxItemSize / 2; } } else if (single) { size = 1; } else if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { // NO OP, the quantity already set (64) is needed for shift } size = Math.min(size, maxItemSize); // Do this before actually extracting, since external storage sends updates as soon as a change happens (so before the storage tracker used to track) network.getItemStorageTracker().changed(player, item.copy()); ItemStack took = network.extractItem(item, size, Action.SIMULATE); if (!took.isEmpty()) { if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { IItemHandler playerInventory = player.getCapability(Capabilities.ItemHandler.ENTITY); if (playerInventory != null) { if (preferredSlot != -1) { ItemStack remainder = playerInventory.insertItem(preferredSlot, took, true); if (remainder.getCount() != took.getCount()) { ItemStack inserted = network.extractItem(item, size - remainder.getCount(), Action.PERFORM); playerInventory.insertItem(preferredSlot, inserted, false); took.setCount(remainder.getCount()); } } if (!took.isEmpty() && ItemHandlerHelper.insertItemStacked(playerInventory, took, true).isEmpty()) { took = network.extractItem(item, size, Action.PERFORM); ItemHandlerHelper.insertItemStacked(playerInventory, took, false); } } } else { took = network.extractItem(item, size, Action.PERFORM); if (!took.isEmpty()) { if (single && !held.isEmpty()) { held.grow(1); } else { player.containerMenu.setCarried(took); } } } network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getExtractUsage()); } } @Override @Nonnull public ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single) { if (!network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) { return stack; } network.getItemStorageTracker().changed(player, stack.copy()); ItemStack remainder; if (single) { if (network.insertItem(stack, 1, Action.SIMULATE).isEmpty()) { network.insertItem(stack, 1, Action.PERFORM); stack.shrink(1); } remainder = stack; } else { remainder = network.insertItem(stack, stack.getCount(), Action.PERFORM); } network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getInsertUsage()); return remainder; } @Override public void onInsertHeldItem(ServerPlayer player, boolean single) { if (player.containerMenu.getCarried().isEmpty() || !network.getSecurityManager().hasPermission(Permission.INSERT, player) || !network.canRun()) { return; } ItemStack stack = player.containerMenu.getCarried(); int size = single ? 1 : stack.getCount(); network.getItemStorageTracker().changed(player, stack.copy()); if (single) { if (network.insertItem(stack, size, Action.SIMULATE).isEmpty()) { network.insertItem(stack, size, Action.PERFORM); stack.shrink(size); } } else { player.containerMenu.setCarried(network.insertItem(stack, size, Action.PERFORM)); } network.getNetworkItemManager().drainEnergy(player, RS.SERVER_CONFIG.getWirelessGrid().getInsertUsage()); } @Override public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) { if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { return; } ItemStack stack = network.getItemStorageCache().getCraftablesList().get(id); if (stack != null) { ICalculationResult result = network.getCraftingManager().create(stack, quantity); if (!result.isOk() && result.getType() != CalculationResultType.MISSING) { RS.NETWORK_HANDLER.sendTo( player, new GridCraftingPreviewResponseMessage( Collections.singletonList(new ErrorCraftingPreviewElement(result.getType(), result.getRecursedPattern() == null ? ItemStack.EMPTY : result.getRecursedPattern().getStack())), id, quantity, false ) ); } else if (result.isOk() && noPreview) { network.getCraftingManager().start(result.getTask()); RS.NETWORK_HANDLER.sendTo(player, new GridCraftingStartResponseMessage()); } else { RS.NETWORK_HANDLER.sendTo( player, new GridCraftingPreviewResponseMessage( result.getPreviewElements(), id, quantity, false ) ); } } } @Override public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) { if (quantity <= 0 || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { return; } ItemStack stack = network.getItemStorageCache().getCraftablesList().get(id); if (stack != null) { ICalculationResult result = network.getCraftingManager().create(stack, quantity); if (result.isOk()) { network.getCraftingManager().start(result.getTask()); } } } @Override public void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id) { if (!network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { return; } network.getCraftingManager().cancel(id); network.getNetworkItemManager().drainEnergy(player, id == null ? RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCancelAllUsage() : RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCancelUsage()); } @Override public void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up) { onInventoryScroll(this, player, slot, shift, up, network); } @Override public void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up) { onGridScroll(this, player, id, shift, up, network); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/PortableFluidGridHandler.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.handler; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Containers; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; import java.util.UUID; public class PortableFluidGridHandler implements IFluidGridHandler { private final IPortableGrid portableGrid; public PortableFluidGridHandler(IPortableGrid portableGrid) { this.portableGrid = portableGrid; } @Override public void onExtract(ServerPlayer player, UUID id, boolean shift) { if (!portableGrid.isGridActive()) { return; } FluidStack stack = portableGrid.getFluidCache().getList().get(id); if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME) { return; } ItemStack bucket = ItemStack.EMPTY; for (int i = 0; i < player.getInventory().getContainerSize(); ++i) { ItemStack slot = player.getInventory().getItem(i); if (API.instance().getComparer().isEqualNoQuantity(StackUtils.EMPTY_BUCKET, slot)) { bucket = StackUtils.EMPTY_BUCKET.copy(); player.getInventory().removeItem(i, 1); break; } } if (!bucket.isEmpty()) { IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM); if (fluidHandler != null) { portableGrid.getFluidStorageTracker().changed(player, stack.copy()); fluidHandler.fill(portableGrid.getFluidStorage().extract(stack, FluidType.BUCKET_VOLUME, IComparer.COMPARE_NBT, Action.PERFORM), IFluidHandler.FluidAction.EXECUTE); if (shift) { if (!player.getInventory().add(fluidHandler.getContainer().copy())) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), fluidHandler.getContainer()); } } else { player.containerMenu.setCarried(fluidHandler.getContainer()); } portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getExtractUsage()); } } } @Override @Nonnull public ItemStack onInsert(ServerPlayer player, ItemStack container) { if (!portableGrid.isGridActive()) { return container; } Pair result = StackUtils.getFluid(container, true); if (!result.getValue().isEmpty() && portableGrid.getFluidStorage().insert(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) { portableGrid.getFluidStorageTracker().changed(player, result.getValue().copy()); result = StackUtils.getFluid(container, false); portableGrid.getFluidStorage().insert(result.getValue(), result.getValue().getAmount(), Action.PERFORM); portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage()); return result.getLeft(); } return container; } @Override public void onInsertHeldContainer(ServerPlayer player) { player.containerMenu.setCarried(onInsert(player, player.containerMenu.getCarried())); } @Override public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) { // NO OP } @Override public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) { // NO OP } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/grid/handler/PortableItemGridHandler.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.grid.handler; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.UUID; public class PortableItemGridHandler implements IItemGridHandler { private final IPortableGrid portableGrid; private final IGrid grid; public PortableItemGridHandler(IPortableGrid portableGrid, IGrid grid) { this.portableGrid = portableGrid; this.grid = grid; } @Override public void onExtract(ServerPlayer player, ItemStack stack, int preferredSlot, int flags) { if (portableGrid.getStorage() == null || !grid.isGridActive()) { return; } if (portableGrid.getItemCache().getList().getEntry(stack, IComparer.COMPARE_NBT) != null) { onExtract(player, portableGrid.getItemCache().getList().getEntry(stack, IComparer.COMPARE_NBT).getId(), preferredSlot, flags); } } @Override public void onExtract(ServerPlayer player, UUID id, int preferredSlot, int flags) { if (portableGrid.getStorage() == null || !grid.isGridActive()) { return; } ItemStack item = portableGrid.getItemCache().getList().get(id); if (item == null) { return; } int itemSize = item.getCount(); // We copy here because some mods change the NBT tag of an item after getting the stack limit int maxItemSize = item.getItem().getMaxStackSize(item.copy()); boolean single = (flags & EXTRACT_SINGLE) == EXTRACT_SINGLE; ItemStack held = player.containerMenu.getCarried(); if (single) { if (!held.isEmpty() && (!API.instance().getComparer().isEqualNoQuantity(item, held) || held.getCount() + 1 > held.getMaxStackSize())) { return; } } else if (!player.containerMenu.getCarried().isEmpty()) { return; } int size = 64; if ((flags & EXTRACT_HALF) == EXTRACT_HALF && itemSize > 1) { size = itemSize / 2; // Rationale for this check: // If we have 32 buckets, and we want to extract half, we expect/need to get 8 (max stack size 16 / 2). // Without this check, we would get 16 (total stack size 32 / 2). // 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). if (size > maxItemSize / 2 && maxItemSize != 1) { size = maxItemSize / 2; } } else if (single) { size = 1; } else if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { // NO OP, the quantity already set (64) is needed for shift } size = Math.min(size, maxItemSize); // Do this before actually extracting, since portable grid sends updates as soon as a change happens (so before the storage tracker used to track) portableGrid.getItemStorageTracker().changed(player, item.copy()); ItemStack took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.SIMULATE); if (!took.isEmpty()) { if ((flags & EXTRACT_SHIFT) == EXTRACT_SHIFT) { IItemHandler playerInventory = player.getCapability(Capabilities.ItemHandler.ENTITY); if (playerInventory != null) { if (preferredSlot != -1) { ItemStack remainder = playerInventory.insertItem(preferredSlot, took, true); if (remainder.getCount() != took.getCount()) { ItemStack inserted = portableGrid.getItemStorage().extract(item, size - remainder.getCount(), IComparer.COMPARE_NBT, Action.PERFORM); playerInventory.insertItem(preferredSlot, inserted, false); took.setCount(remainder.getCount()); } } if (!took.isEmpty() && ItemHandlerHelper.insertItemStacked(playerInventory, took, true).isEmpty()) { took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.PERFORM); ItemHandlerHelper.insertItemStacked(playerInventory, took, false); } } } else { took = portableGrid.getItemStorage().extract(item, size, IComparer.COMPARE_NBT, Action.PERFORM); if (single && !held.isEmpty()) { held.grow(1); } else { player.containerMenu.setCarried(took); } } portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getExtractUsage()); } } @Override @Nonnull public ItemStack onInsert(ServerPlayer player, ItemStack stack, boolean single) { if (portableGrid.getStorage() == null || !grid.isGridActive()) { return stack; } portableGrid.getItemStorageTracker().changed(player, stack.copy()); ItemStack remainder; if (single) { if (portableGrid.getItemStorage().insert(stack, 1, Action.SIMULATE).isEmpty()) { portableGrid.getItemStorage().insert(stack, 1, Action.PERFORM); stack.shrink(1); } remainder = stack; } else { remainder = portableGrid.getItemStorage().insert(stack, stack.getCount(), Action.PERFORM); } portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage()); return remainder; } @Override public void onInsertHeldItem(ServerPlayer player, boolean single) { if (player.containerMenu.getCarried().isEmpty() || portableGrid.getStorage() == null || !grid.isGridActive()) { return; } ItemStack stack = player.containerMenu.getCarried(); int size = single ? 1 : stack.getCount(); portableGrid.getItemStorageTracker().changed(player, stack.copy()); if (single) { if (portableGrid.getItemStorage().insert(stack, size, Action.SIMULATE).isEmpty()) { portableGrid.getItemStorage().insert(stack, size, Action.PERFORM); stack.shrink(size); } } else { player.containerMenu.setCarried(portableGrid.getItemStorage().insert(stack, size, Action.PERFORM)); } portableGrid.drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getInsertUsage()); } @Override public void onCraftingPreviewRequested(ServerPlayer player, UUID id, int quantity, boolean noPreview) { // NO OP } @Override public void onCraftingRequested(ServerPlayer player, UUID id, int quantity) { // NO OP } @Override public void onCraftingCancelRequested(ServerPlayer player, @Nullable UUID id) { // NO OP } @Override public void onInventoryScroll(ServerPlayer player, int slot, boolean shift, boolean up) { ItemGridHandler.onInventoryScroll(this, player, slot, shift, up, null); } @Override public void onGridScroll(ServerPlayer player, @Nullable UUID id, boolean shift, boolean up) { ItemGridHandler.onGridScroll(this, player, id, shift, up, null); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/NetworkItemManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.item; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.network.IWirelessTransmitter; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.item.INetworkItemProvider; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class NetworkItemManager implements INetworkItemManager { private final INetwork network; private final Map items = new ConcurrentHashMap<>(); public NetworkItemManager(INetwork network) { this.network = network; } @Override public void open(Player player, ItemStack stack, PlayerSlot slot) { boolean inRange = false; for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) { INetworkNode node = entry.getNode(); if (node instanceof IWirelessTransmitter && network.canRun() && node.isActive() && ((IWirelessTransmitter) node).getDimension() == player.getCommandSenderWorld().dimension()) { IWirelessTransmitter transmitter = (IWirelessTransmitter) node; Vec3 pos = player.position(); 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)); if (distance < transmitter.getRange()) { inRange = true; break; } } } if (!inRange) { player.sendSystemMessage(Component.translatable("misc.refinedstorage.network_item.out_of_range")); return; } INetworkItem item = ((INetworkItemProvider) stack.getItem()).provide(this, player, stack, slot); if (item.onOpen(network)) { items.put(player, item); } } @Override public void close(Player player) { items.remove(player); } @Override public INetworkItem getItem(Player player) { return items.get(player); } @Override public void drainEnergy(Player player, int energy) { INetworkItem item = getItem(player); if (item != null) { item.drainEnergy(energy); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessCraftingMonitorNetworkItem.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor; import com.refinedmods.refinedstorage.container.factory.CraftingMonitorMenuProvider; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; public class WirelessCraftingMonitorNetworkItem implements INetworkItem { private final INetworkItemManager handler; private final Player player; private final ItemStack stack; private final PlayerSlot slot; public WirelessCraftingMonitorNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { this.handler = handler; this.player = player; this.stack = stack; this.slot = slot; } @Override public Player getPlayer() { return player; } @Override public boolean onOpen(INetwork network) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (RS.SERVER_CONFIG.getWirelessCraftingMonitor().getUseEnergy() && ((WirelessCraftingMonitorItem) stack.getItem()).getType() != WirelessCraftingMonitorItem.Type.CREATIVE && energy != null && energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessCraftingMonitor().getOpenUsage()) { sendOutOfEnergyMessage(); return false; } if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player) || !network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player)) { LevelUtils.sendNoPermissionMessage(player); return false; } WirelessCraftingMonitor wirelessCraftingMonitor = new WirelessCraftingMonitor(stack, player.getServer(), slot); player.openMenu( new CraftingMonitorMenuProvider(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), wirelessCraftingMonitor, null), slot::writePlayerSlot ); drainEnergy(RS.SERVER_CONFIG.getWirelessCraftingMonitor().getOpenUsage()); return true; } @Override public void drainEnergy(int energy) { if (RS.SERVER_CONFIG.getWirelessCraftingMonitor().getUseEnergy() && ((WirelessCraftingMonitorItem) stack.getItem()).getType() != WirelessCraftingMonitorItem.Type.CREATIVE) { IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyStorage != null) { energyStorage.extractEnergy(energy, false); if (energyStorage.getEnergyStored() <= 0) { handler.close(player); player.closeContainer(); sendOutOfEnergyMessage(); } } } } private void sendOutOfEnergyMessage() { player.sendSystemMessage(Component.translatable("misc.refinedstorage.network_item.out_of_energy", Component.translatable(stack.getItem().getDescriptionId()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessFluidGridNetworkItem.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessFluidGridGridFactory; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.WirelessFluidGridItem; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; public class WirelessFluidGridNetworkItem implements INetworkItem { private final INetworkItemManager handler; private final Player player; private final ItemStack stack; private final PlayerSlot slot; public WirelessFluidGridNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { this.handler = handler; this.player = player; this.stack = stack; this.slot = slot; } @Override public Player getPlayer() { return player; } @Override public boolean onOpen(INetwork network) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (RS.SERVER_CONFIG.getWirelessFluidGrid().getUseEnergy() && ((WirelessFluidGridItem) stack.getItem()).getType() != WirelessFluidGridItem.Type.CREATIVE && energy != null && energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessFluidGrid().getOpenUsage()) { sendOutOfEnergyMessage(); return false; } if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player)) { LevelUtils.sendNoPermissionMessage(player); return false; } API.instance().getGridManager().openGrid(WirelessFluidGridGridFactory.ID, (ServerPlayer) player, stack, slot); drainEnergy(RS.SERVER_CONFIG.getWirelessFluidGrid().getOpenUsage()); return true; } @Override public void drainEnergy(int energy) { if (RS.SERVER_CONFIG.getWirelessFluidGrid().getUseEnergy() && ((WirelessFluidGridItem) stack.getItem()).getType() != WirelessFluidGridItem.Type.CREATIVE) { IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyStorage != null) { energyStorage.extractEnergy(energy, false); if (energyStorage.getEnergyStored() <= 0) { handler.close(player); player.closeContainer(); sendOutOfEnergyMessage(); } } } } private void sendOutOfEnergyMessage() { player.sendSystemMessage(Component.translatable("misc.refinedstorage.network_item.out_of_energy", Component.translatable(stack.getItem().getDescriptionId()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/item/WirelessGridNetworkItem.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessGridGridFactory; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; public class WirelessGridNetworkItem implements INetworkItem { private final INetworkItemManager handler; private final Player player; private final ItemStack stack; private final PlayerSlot slot; public WirelessGridNetworkItem(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { this.handler = handler; this.player = player; this.stack = stack; this.slot = slot; } @Override public Player getPlayer() { return player; } @Override public boolean onOpen(INetwork network) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (RS.SERVER_CONFIG.getWirelessGrid().getUseEnergy() && ((WirelessGridItem) stack.getItem()).getType() != WirelessGridItem.Type.CREATIVE && energy != null && energy.getEnergyStored() <= RS.SERVER_CONFIG.getWirelessGrid().getOpenUsage()) { sendOutOfEnergyMessage(); return false; } if (!network.getSecurityManager().hasPermission(Permission.MODIFY, player)) { LevelUtils.sendNoPermissionMessage(player); return false; } API.instance().getGridManager().openGrid(WirelessGridGridFactory.ID, (ServerPlayer) player, stack, slot); drainEnergy(RS.SERVER_CONFIG.getWirelessGrid().getOpenUsage()); return true; } @Override public void drainEnergy(int energy) { if (RS.SERVER_CONFIG.getWirelessGrid().getUseEnergy() && ((WirelessGridItem) stack.getItem()).getType() != WirelessGridItem.Type.CREATIVE) { IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyStorage != null) { energyStorage.extractEnergy(energy, false); if (energyStorage.getEnergyStored() <= 0) { handler.close(player); player.closeContainer(); sendOutOfEnergyMessage(); } } } } private void sendOutOfEnergyMessage() { player.sendSystemMessage(Component.translatable("misc.refinedstorage.network_item.out_of_energy", Component.translatable(stack.getItem().getDescriptionId()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CableNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; public class CableNetworkNode extends NetworkNode implements ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "cable"); private final CoverManager coverManager; public CableNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public boolean canConduct(Direction direction) { return !coverManager.hasCover(direction) || coverManager.getCover(direction).getType() == CoverType.HOLLOW; } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getCable().getUsage(); } @Override public ResourceLocation getId() { return ID; } @Override public CoverManager getCoverManager() { return coverManager; } @Override public void read(CompoundTag tag) { if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } super.read(tag); } @Override public CompoundTag write(CompoundTag tag) { tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); return super.write(tag); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ConnectivityStateChangeCause.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; public enum ConnectivityStateChangeCause { GRAPH_CHANGE, REDSTONE_MODE_OR_NETWORK_ENERGY_CHANGE } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ConstructorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.FluidUtil; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import javax.annotation.Nullable; public class ConstructorNetworkNode extends NetworkNode implements IComparable, IType, ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "constructor"); private static final String NBT_COMPARE = "Compare"; private static final String NBT_TYPE = "Type"; private static final String NBT_DROP = "Drop"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private static final int BASE_SPEED = 20; private final BaseItemHandler itemFilters = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(1) .addListener(new NetworkNodeFluidInventoryListener(this)); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.CRAFTING, UpgradeItem.Type.STACK) .addListener(new NetworkNodeInventoryListener(this)); private final CoverManager coverManager; private int compare = IComparer.COMPARE_NBT; private int type = IType.ITEMS; private boolean drop = false; public ConstructorNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getConstructor().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && level.isLoaded(pos)) { if (type == IType.ITEMS && !itemFilters.getStackInSlot(0).isEmpty()) { ItemStack stack = itemFilters.getStackInSlot(0); if (drop) { extractAndDropItem(stack); } else if (stack.getItem() == Items.FIREWORK_ROCKET) { extractAndSpawnFireworks(stack); } else if (stack.getItem() instanceof BlockItem) { extractAndPlaceBlock(stack); } } else if (type == IType.FLUIDS && !fluidFilters.getFluid(0).isEmpty()) { extractAndPlaceFluid(fluidFilters.getFluid(0)); } } } private void extractAndPlaceFluid(FluidStack stack) { BlockPos front = pos.relative(getDirection()); if (network.extractFluid(stack, FluidType.BUCKET_VOLUME, compare, Action.SIMULATE).getAmount() < FluidType.BUCKET_VOLUME) { if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(this, stack, FluidType.BUCKET_VOLUME); } } else if (!level.getBlockState(front).getFluidState().isSource()) { FluidUtil.tryPlaceFluid(LevelUtils.getFakePlayer((ServerLevel) level, getOwner()), level, InteractionHand.MAIN_HAND, front, new NetworkFluidHandler(StackUtils.copy(stack, FluidType.BUCKET_VOLUME)), stack); } } private void extractAndPlaceBlock(ItemStack stack) { ItemStack took = network.extractItem(stack, 1, compare, Action.SIMULATE); if (!took.isEmpty()) { // We have to copy took as the forge hook clears the item. final ItemStack tookCopy = took.copy(); BlockPlaceContext ctx = new ConstructorBlockItemUseContext( level, LevelUtils.getFakePlayer((ServerLevel) level, getOwner()), InteractionHand.MAIN_HAND, took, new BlockHitResult(Vec3.ZERO, getDirection(), pos, false) ); InteractionResult result = CommonHooks.onPlaceItemIntoWorld(ctx); if (result.consumesAction()) { network.extractItem(tookCopy, 1, Action.PERFORM); } } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { ItemStack craft = itemFilters.getStackInSlot(0); network.getCraftingManager().request(this, craft, 1); } } private void extractAndDropItem(ItemStack stack) { int dropCount = Math.min(upgrades.getStackInteractCount(), stack.getMaxStackSize()); ItemStack took = network.extractItem(stack, dropCount, compare, Action.PERFORM); if (!took.isEmpty()) { DefaultDispenseItemBehavior.spawnItem(level, took, 6, getDirection(), new Vec3(getDispensePositionX(), getDispensePositionY(), getDispensePositionZ())); } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(this, stack, 1); } } private void extractAndSpawnFireworks(ItemStack stack) { ItemStack took = network.extractItem(stack, 1, compare, Action.PERFORM); if (!took.isEmpty()) { level.addFreshEntity(new FireworkRocketEntity(level, getDispensePositionX(), getDispensePositionY(), getDispensePositionZ(), took)); } } private double getDispensePositionX() { return (double) pos.getX() + 0.5D + 0.8D * (double) getDirection().getStepX(); } private double getDispensePositionY() { return (double) pos.getY() + (getDirection() == Direction.DOWN ? 0.45D : 0.5D) + 0.8D * (double) getDirection().getStepY(); } private double getDispensePositionZ() { return (double) pos.getZ() + 0.5D + 0.8D * (double) getDirection().getStepZ(); } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } StackUtils.readItems(upgrades, 1, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); StackUtils.writeItems(upgrades, 1, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_TYPE, type); tag.putBoolean(NBT_DROP, drop); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } if (tag.contains(NBT_DROP)) { drop = tag.getBoolean(NBT_DROP); } StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } public boolean isDrop() { return drop; } public void setDrop(boolean drop) { this.drop = drop; } public IItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return getUpgrades(); } @Override public int getType() { return level.isClientSide ? ConstructorBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } @Override public CoverManager getCoverManager() { return coverManager; } private static class ConstructorBlockItemUseContext extends BlockPlaceContext { public ConstructorBlockItemUseContext(Level level, @Nullable Player player, InteractionHand hand, ItemStack stack, BlockHitResult rayTraceResult) { super(level, player, hand, stack, rayTraceResult); } } private class NetworkFluidHandler implements IFluidHandler { private final FluidStack resource; public NetworkFluidHandler(FluidStack resource) { this.resource = resource; } @Override public int getTanks() { throw new UnsupportedOperationException(); } @Nonnull @Override public FluidStack getFluidInTank(int tank) { throw new UnsupportedOperationException(); } @Override public int getTankCapacity(int tank) { throw new UnsupportedOperationException(); } @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { throw new UnsupportedOperationException(); } @Override public int fill(FluidStack resource, FluidAction action) { throw new UnsupportedOperationException(); } @Nonnull @Override public FluidStack drain(FluidStack resource, FluidAction action) { return network.extractFluid(resource, resource.getAmount(), compare, action == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM); } @Nonnull @Override public FluidStack drain(int maxDrain, FluidAction action) { return network.extractFluid(resource, resource.getAmount(), compare, action == FluidAction.SIMULATE ? Action.SIMULATE : Action.PERFORM); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CrafterManagerNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.block.CrafterManagerBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; public class CrafterManagerNetworkNode extends NetworkNode { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "crafter_manager"); private static final String NBT_SIZE = "Size"; private static final String NBT_SEARCH_BOX_MODE = "SearchBoxMode"; private int size = IGrid.SIZE_STRETCH; private int searchBoxMode = IGrid.SEARCH_BOX_MODE_NORMAL; public CrafterManagerNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getCrafterManager().getUsage(); } @Override public ResourceLocation getId() { return ID; } public int getSize() { return level.isClientSide ? CrafterManagerBlockEntity.SIZE.getValue() : size; } public void setSize(int size) { this.size = size; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_SIZE, size); tag.putInt(NBT_SEARCH_BOX_MODE, searchBoxMode); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_SIZE)) { size = tag.getInt(NBT_SIZE); } if (tag.contains(NBT_SEARCH_BOX_MODE)) { searchBoxMode = tag.getInt(NBT_SEARCH_BOX_MODE); } } public int getSearchBoxMode() { return level.isClientSide ? CrafterManagerBlockEntity.SEARCH_BOX_MODE.getValue() : searchBoxMode; } public void setSearchBoxMode(int searchBoxMode) { this.searchBoxMode = searchBoxMode; } public boolean isActiveOnClient() { BlockState state = level.getBlockState(pos); if (state.getBlock() instanceof CrafterManagerBlock) { return state.getValue(NetworkNodeBlock.CONNECTED); } return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CrafterNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.PatternItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Nameable; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; public class CrafterNetworkNode extends NetworkNode implements ICraftingPatternContainer { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "crafter"); private static final Component DEFAULT_NAME = Component.translatable("gui.refinedstorage.crafter"); private static final String NBT_DISPLAY_NAME = "DisplayName"; private static final String NBT_UUID = "CrafterUuid"; private static final String NBT_MODE = "Mode"; private static final String NBT_LOCKED = "Locked"; private static final String NBT_WAS_POWERED = "WasPowered"; private final List patterns = new ArrayList<>(); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED) .addListener(new NetworkNodeInventoryListener(this)); // Used to prevent infinite recursion on getRootContainer() when there's e.g. two crafters facing each other. private boolean visited = false; private final BaseItemHandler patternsInventory = new BaseItemHandler(9) { @Override public int getSlotLimit(int slot) { return 1; } @Nonnull @Override public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { if (!stacks.get(slot).isEmpty()) { return stack; } return super.insertItem(slot, stack, simulate); } } .addValidator(new PatternItemValidator(level)) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!reading) { if (!level.isClientSide) { invalidate(); } if (network != null) { network.getCraftingManager().invalidate(); } } }); private CrafterMode mode = CrafterMode.IGNORE; private boolean locked = false; private boolean wasPowered; @Nullable private Component displayName; @Nullable private UUID uuid = null; public CrafterNetworkNode(Level level, BlockPos pos) { super(level, pos); } private void invalidate() { patterns.clear(); for (int i = 0; i < patternsInventory.getSlots(); ++i) { ItemStack patternStack = patternsInventory.getStackInSlot(i); if (!patternStack.isEmpty()) { ICraftingPattern pattern = ((ICraftingPatternProvider) patternStack.getItem()).create(level, patternStack, this); if (pattern.isValid()) { patterns.add(pattern); } } } } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getCrafter().getUsage() + upgrades.getEnergyUsage() + (RS.SERVER_CONFIG.getCrafter().getPatternUsage() * patterns.size()); } @Override public void update() { super.update(); if (ticks == 1) { invalidate(); } if (mode == CrafterMode.PULSE_INSERTS_NEXT_SET && level.isLoaded(pos)) { if (level.hasNeighborSignal(pos)) { this.wasPowered = true; markDirty(); } else if (wasPowered) { this.wasPowered = false; this.locked = false; markDirty(); } } } @Override protected void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); network.getCraftingManager().invalidate(); } @Override public void onDisconnected(INetwork network) { super.onDisconnected(network); network.getCraftingManager().getTasks().stream() .filter(task -> task.getPattern().getContainer().getPosition().equals(pos)) .forEach(task -> network.getCraftingManager().cancel(task.getId())); } @Override public void onDirectionChanged(Direction direction) { super.onDirectionChanged(direction); if (network != null) { network.getCraftingManager().invalidate(); } level.invalidateCapabilities(pos); } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(patternsInventory, 0, tag); invalidate(); StackUtils.readItems(upgrades, 1, tag); if (tag.contains(NBT_DISPLAY_NAME)) { displayName = Component.Serializer.fromJson(tag.getString(NBT_DISPLAY_NAME)); } if (tag.hasUUID(NBT_UUID)) { uuid = tag.getUUID(NBT_UUID); } if (tag.contains(NBT_MODE)) { mode = CrafterMode.getById(tag.getInt(NBT_MODE)); } if (tag.contains(NBT_LOCKED)) { locked = tag.getBoolean(NBT_LOCKED); } if (tag.contains(NBT_WAS_POWERED)) { wasPowered = tag.getBoolean(NBT_WAS_POWERED); } } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(patternsInventory, 0, tag); StackUtils.writeItems(upgrades, 1, tag); if (displayName != null) { tag.putString(NBT_DISPLAY_NAME, Component.Serializer.toJson(displayName)); } if (uuid != null) { tag.putUUID(NBT_UUID, uuid); } tag.putInt(NBT_MODE, mode.ordinal()); tag.putBoolean(NBT_LOCKED, locked); tag.putBoolean(NBT_WAS_POWERED, wasPowered); return tag; } @Override public int getUpdateInterval() { switch (upgrades.getUpgradeCount(UpgradeItem.Type.SPEED)) { case 0: return 10; case 1: return 8; case 2: return 6; case 3: return 4; case 4: return 2; default: return 0; } } @Override public int getMaximumSuccessfulCraftingUpdates() { switch (upgrades.getUpgradeCount(UpgradeItem.Type.SPEED)) { case 0: return 1; case 1: return 2; case 2: return 3; case 3: return 4; case 4: return 5; default: return 1; } } @Override @Nullable public IItemHandler getConnectedInventory() { ICraftingPatternContainer proxy = getRootContainer(); if (proxy == null) { return null; } return LevelUtils.getItemHandler(level, proxy.getPosition().relative(proxy.getDirection()), proxy.getDirection().getOpposite()); } @Nullable @Override public IFluidHandler getConnectedFluidInventory() { ICraftingPatternContainer proxy = getRootContainer(); if (proxy == null) { return null; } return LevelUtils.getFluidHandler(level, proxy.getPosition().relative(proxy.getDirection()), proxy.getDirection().getOpposite()); } @Override @Nullable public BlockEntity getConnectedBlockEntity() { ICraftingPatternContainer proxy = getRootContainer(); if (proxy == null) { return null; } return proxy.getFacingBlockEntity(); } @Override public List getPatterns() { return patterns; } @Override @Nullable public IItemHandlerModifiable getPatternInventory() { return patternsInventory; } @Override @Nullable public Component getCustomName() { return displayName; } @Override public Component getName() { ICraftingPatternContainer root = getRootContainer(); if (root != null) { Component displayNameOfRoot = root.getCustomName(); if (displayNameOfRoot != null) { return displayNameOfRoot; } } BlockEntity facing = getConnectedBlockEntity(); if (facing instanceof Nameable && ((Nameable) facing).getName() != null) { return ((Nameable) facing).getName(); } if (facing != null) { return Component.translatable(level.getBlockState(facing.getBlockPos()).getBlock().getDescriptionId()); } return DEFAULT_NAME; } @Nullable public Component getDisplayName() { return displayName; } public void setDisplayName(Component displayName) { this.displayName = displayName; } @Override public BlockPos getPosition() { return pos; } public CrafterMode getMode() { return mode; } public void setMode(CrafterMode mode) { this.mode = mode; this.wasPowered = false; this.locked = false; this.markDirty(); } public IItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return new CombinedInvWrapper(patternsInventory, upgrades); } @Override @Nullable public ICraftingPatternContainer getRootContainer() { if (visited) { return null; } INetworkNode facing = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(getDirection())); if (!(facing instanceof ICraftingPatternContainer) || facing.getNetwork() != network) { return this; } visited = true; ICraftingPatternContainer facingContainer = ((ICraftingPatternContainer) facing).getRootContainer(); visited = false; return facingContainer; } public Optional getRootContainerNotSelf() { ICraftingPatternContainer root = getRootContainer(); if (root != null && root != this) { return Optional.of(root); } return Optional.empty(); } @Override public UUID getUuid() { if (this.uuid == null) { this.uuid = UUID.randomUUID(); markDirty(); } return uuid; } @Override public boolean isLocked() { Optional root = getRootContainerNotSelf(); if (root.isPresent()) { return root.get().isLocked(); } switch (mode) { case IGNORE: return false; case SIGNAL_LOCKS_AUTOCRAFTING: return level.hasNeighborSignal(pos); case SIGNAL_UNLOCKS_AUTOCRAFTING: return !level.hasNeighborSignal(pos); case PULSE_INSERTS_NEXT_SET: return locked; default: return false; } } @Override public void unlock() { locked = false; } @Override public void onUsedForProcessing() { Optional root = getRootContainerNotSelf(); if (root.isPresent()) { root.get().onUsedForProcessing(); return; } if (mode == CrafterMode.PULSE_INSERTS_NEXT_SET) { this.locked = true; markDirty(); } } public enum CrafterMode { IGNORE, SIGNAL_UNLOCKS_AUTOCRAFTING, SIGNAL_LOCKS_AUTOCRAFTING, PULSE_INSERTS_NEXT_SET; public static CrafterMode getById(int id) { if (id >= 0 && id < values().length) { return values()[id]; } return IGNORE; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/CraftingMonitorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.block.CraftingMonitorBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.UUID; public class CraftingMonitorNetworkNode extends NetworkNode implements ICraftingMonitor { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "crafting_monitor"); private static final String NBT_TAB_SELECTED = "TabSelected"; private static final String NBT_TAB_PAGE = "TabPage"; private Optional tabSelected = Optional.empty(); private int tabPage; public CraftingMonitorNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getCraftingMonitor().getUsage(); } @Override public ResourceLocation getId() { return ID; } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.crafting_monitor"); } @Override public void onCancelled(ServerPlayer player, @Nullable UUID id) { if (network != null) { network.getItemGridHandler().onCraftingCancelRequested(player, id); } } @Override public BlockEntitySynchronizationParameter getRedstoneModeParameter() { return NetworkNodeBlockEntity.REDSTONE_MODE; } @Override public Collection getTasks() { return network != null ? network.getCraftingManager().getTasks() : Collections.emptyList(); } @Nullable @Override public ICraftingManager getCraftingManager() { return network != null ? network.getCraftingManager() : null; } @Override public boolean isActiveOnClient() { BlockState state = level.getBlockState(pos); if (state.getBlock() instanceof CraftingMonitorBlock) { return state.getValue(NetworkNodeBlock.CONNECTED); } return false; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.putInt(NBT_TAB_PAGE, tabPage); tabSelected.ifPresent(uuid -> tag.putUUID(NBT_TAB_SELECTED, uuid)); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(NBT_TAB_PAGE)) { tabPage = tag.getInt(NBT_TAB_PAGE); } if (tag.hasUUID(NBT_TAB_SELECTED)) { tabSelected = Optional.of(tag.getUUID(NBT_TAB_SELECTED)); } } @Override public void onClosed(Player player) { // NO OP } @Override public Optional getTabSelected() { return level.isClientSide ? CraftingMonitorBlockEntity.TAB_SELECTED.getValue() : tabSelected; } public void setTabSelected(Optional tabSelected) { this.tabSelected = tabSelected; } @Override public int getTabPage() { return level.isClientSide ? CraftingMonitorBlockEntity.TAB_PAGE.getValue() : tabPage; } public void setTabPage(int tabPage) { this.tabPage = tabPage; } @Override public void onTabSelectionChanged(Optional tab) { BlockEntitySynchronizationManager.setParameter(CraftingMonitorBlockEntity.TAB_SELECTED, tab); } @Override public void onTabPageChanged(int page) { if (page >= 0) { BlockEntitySynchronizationManager.setParameter(CraftingMonitorBlockEntity.TAB_PAGE, page); } } @Override public int getSlotId() { return -1; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DestructorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.level.BlockEvent; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.IFluidBlock; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import java.util.List; public class DestructorNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "destructor"); private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_TYPE = "Type"; private static final String NBT_PICKUP = "Pickup"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private static final int BASE_SPEED = 20; private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final CoverManager coverManager; private int compare = IComparer.COMPARE_NBT; 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) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> tool = createTool()); private int mode = IWhitelistBlacklist.BLACKLIST; private int type = IType.ITEMS; private boolean pickupItem = false; public DestructorNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getDestructor().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (canUpdate() && ticks % upgrades.getSpeed(BASE_SPEED, 4) == 0 && level.isLoaded(pos)) { if (type == IType.ITEMS) { if (pickupItem) { pickupItems(); } else { breakBlock(); } } else if (type == IType.FLUIDS) { breakFluid(); } } } private ItemStack tool = createTool(); private void pickupItems() { BlockPos front = pos.relative(getDirection()); if (!level.isLoaded(front)) { return; } List droppedItems = level.getEntitiesOfClass(ItemEntity.class, new AABB(front)); for (ItemEntity entity : droppedItems) { if (entity.isRemoved()) { continue; } ItemStack droppedItem = entity.getItem(); if (IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, droppedItem) && network.insertItem(droppedItem, droppedItem.getCount(), Action.SIMULATE).isEmpty()) { network.insertItemTracked(droppedItem.copy(), droppedItem.getCount()); entity.remove(Entity.RemovalReason.DISCARDED); break; } } } private void breakBlock() { BlockPos front = pos.relative(getDirection()); if (!level.isLoaded(front)) { return; } BlockState frontBlockState = level.getBlockState(front); Block frontBlock = frontBlockState.getBlock(); ItemStack frontStack = frontBlock.getCloneItemStack( frontBlockState, new BlockHitResult(Vec3.ZERO, getDirection().getOpposite(), front, false), level, front, LevelUtils.getFakePlayer((ServerLevel) level, getOwner()) ); if (!frontStack.isEmpty() && IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, frontStack) && frontBlockState.getDestroySpeed(level, front) != -1.0) { List drops = Block.getDrops( frontBlockState, (ServerLevel) level, front, level.getBlockEntity(front), LevelUtils.getFakePlayer((ServerLevel) level, getOwner()), tool ); for (ItemStack drop : drops) { if (!network.insertItem(drop, drop.getCount(), Action.SIMULATE).isEmpty()) { return; } } BlockEvent.BreakEvent e = new BlockEvent.BreakEvent(level, front, frontBlockState, LevelUtils.getFakePlayer((ServerLevel) level, getOwner())); if (!NeoForge.EVENT_BUS.post(e).isCanceled()) { frontBlock.playerWillDestroy(level, front, frontBlockState, LevelUtils.getFakePlayer((ServerLevel) level, getOwner())); level.removeBlock(front, false); for (ItemStack drop : drops) { // We check if the controller isn't null here because when a destructor faces a node and removes it // it will essentially remove this block itself from the network without knowing if (network == null) { Containers.dropItemStack(level, front.getX(), front.getY(), front.getZ(), drop); } else { network.insertItemTracked(drop, drop.getCount()); } } } } } private void breakFluid() { BlockPos front = pos.relative(getDirection()); if (!level.isLoaded(front)) { return; } BlockState frontBlockState = level.getBlockState(front); Block frontBlock = frontBlockState.getBlock(); if (frontBlock instanceof LiquidBlock) { // @Volatile: Logic from FlowingFluidBlock#pickupFluid if (frontBlockState.getValue(LiquidBlock.LEVEL) == 0) { Fluid fluid = ((LiquidBlock) frontBlock).getFluid(); FluidStack stack = new FluidStack(fluid, FluidType.BUCKET_VOLUME); if (IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, stack) && network.insertFluid(stack, stack.getAmount(), Action.SIMULATE).isEmpty()) { network.insertFluidTracked(stack, stack.getAmount()); level.setBlock(front, Blocks.AIR.defaultBlockState(), 11); } } } else if (frontBlock instanceof IFluidBlock) { IFluidBlock fluidBlock = (IFluidBlock) frontBlock; if (fluidBlock.canDrain(level, front)) { FluidStack simulatedDrain = fluidBlock.drain(level, front, IFluidHandler.FluidAction.SIMULATE); if (IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, simulatedDrain) && network.insertFluid(simulatedDrain, simulatedDrain.getAmount(), Action.SIMULATE).isEmpty()) { FluidStack drained = fluidBlock.drain(level, front, IFluidHandler.FluidAction.EXECUTE); network.insertFluidTracked(drained, drained.getAmount()); } } } } private ItemStack createTool() { ItemStack newTool = new ItemStack(Items.DIAMOND_PICKAXE); if (upgrades.hasUpgrade(UpgradeItem.Type.SILK_TOUCH)) { newTool.enchant(Enchantments.SILK_TOUCH, 1); } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_3)) { newTool.enchant(Enchantments.BLOCK_FORTUNE, 3); } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_2)) { newTool.enchant(Enchantments.BLOCK_FORTUNE, 2); } else if (upgrades.hasUpgrade(UpgradeItem.Type.FORTUNE_1)) { newTool.enchant(Enchantments.BLOCK_FORTUNE, 1); } return newTool; } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } StackUtils.readItems(upgrades, 1, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); StackUtils.writeItems(upgrades, 1, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_TYPE, type); tag.putBoolean(NBT_PICKUP, pickupItem); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } if (tag.contains(NBT_PICKUP)) { pickupItem = tag.getBoolean(NBT_PICKUP); } StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } public IItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return getUpgrades(); } @Override public int getType() { return level.isClientSide ? DestructorBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } public boolean isPickupItem() { return pickupItem; } public void setPickupItem(boolean pickupItem) { this.pickupItem = pickupItem; } @Override public CoverManager getCoverManager() { return coverManager; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DetectorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.block.DetectorBlock; import com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; public class DetectorNetworkNode extends NetworkNode implements IComparable, IType { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "detector"); public static final int MODE_UNDER = 0; public static final int MODE_EQUAL = 1; public static final int MODE_ABOVE = 2; private static final int SPEED = 5; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_AMOUNT = "Amount"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private final BaseItemHandler itemFilters = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(1).addListener(new NetworkNodeFluidInventoryListener(this)); private int compare = IComparer.COMPARE_NBT; private int type = IType.ITEMS; private int mode = MODE_EQUAL; private int amount = 0; private boolean powered = false; private boolean wasPowered; public DetectorNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getDetector().getUsage(); } @Override public void update() { super.update(); if (powered != wasPowered && level.isLoaded(pos)) { wasPowered = powered; level.setBlockAndUpdate(pos, level.getBlockState(pos).setValue(DetectorBlock.POWERED, powered)); level.updateNeighborsAt(pos, level.getBlockState(pos).getBlock()); } if (canUpdate() && ticks % SPEED == 0) { if (type == IType.ITEMS) { ItemStack slot = itemFilters.getStackInSlot(0); if (!slot.isEmpty()) { ItemStack stack = network.getItemStorageCache().getList().get(slot, compare); powered = isPowered(stack == null ? null : stack.getCount()); } else { powered = isPowered(network.getItemStorageCache().getList().getStacks().stream().map(e -> e.getStack().getCount()).mapToInt(Number::intValue).sum()); } } else if (type == IType.FLUIDS) { FluidStack slot = fluidFilters.getFluid(0); if (!slot.isEmpty()) { FluidStack stack = network.getFluidStorageCache().getList().get(slot, compare); powered = isPowered(stack == null ? null : stack.getAmount()); } else { powered = isPowered(network.getFluidStorageCache().getList().getStacks().stream().map(e -> e.getStack().getAmount()).mapToInt(Number::intValue).sum()); } } } } @Override public ResourceLocation getId() { return ID; } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); if (!state) { powered = false; } } public boolean isPowered() { return powered; } public void setPowered(boolean powered) { this.powered = powered; } private boolean isPowered(@Nullable Integer size) { if (size != null) { switch (mode) { case MODE_UNDER: return size < amount; case MODE_EQUAL: return size == amount; case MODE_ABOVE: return size > amount; default: return false; } } else { if (mode == MODE_UNDER && amount != 0) { return true; } return mode == MODE_EQUAL && amount == 0; } } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } public int getMode() { return mode; } public void setMode(int mode) { this.mode = mode; } public int getAmount() { return amount; } public void setAmount(int amount) { this.amount = amount; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_AMOUNT, amount); tag.putInt(NBT_TYPE, type); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_AMOUNT)) { amount = tag.getInt(NBT_AMOUNT); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } @Override public void setRedstoneMode(RedstoneMode mode) { // NO OP } @Override public int getType() { return level.isClientSide ? DetectorBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/DiskState.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; public enum DiskState { NONE, NORMAL, DISCONNECTED, NEAR_CAPACITY, FULL; public static final int DISK_NEAR_CAPACITY_THRESHOLD = 75; public static DiskState get(int stored, int capacity) { if (stored == capacity) { return FULL; } else if ((int) ((float) stored / (float) capacity * 100F) >= DISK_NEAR_CAPACITY_THRESHOLD) { return NEAR_CAPACITY; } else { return NORMAL; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ExporterNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.ItemHandlerHelper; public class ExporterNetworkNode extends NetworkNode implements IComparable, IType, ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "exporter"); private static final String NBT_COMPARE = "Compare"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final CoverManager coverManager; private int compare = IComparer.COMPARE_NBT; private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.CRAFTING, UpgradeItem.Type.STACK, UpgradeItem.Type.REGULATOR) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!reading && !getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR)) { boolean changed = false; for (int i = 0; i < itemFilters.getSlots(); ++i) { ItemStack filteredItem = itemFilters.getStackInSlot(i); if (filteredItem.getCount() > 1) { filteredItem.setCount(1); changed = true; } } for (int i = 0; i < fluidFilters.getSlots(); ++i) { FluidStack filteredFluid = fluidFilters.getFluid(i); if (!filteredFluid.isEmpty() && filteredFluid.getAmount() != FluidType.BUCKET_VOLUME) { filteredFluid.setAmount(FluidType.BUCKET_VOLUME); changed = true; } } if (changed) { markDirty(); } } }); private int type = IType.ITEMS; private int filterSlot; public ExporterNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getExporter().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (canUpdate() && ticks % upgrades.getSpeed() == 0 && level.isLoaded(pos)) { if (type == IType.ITEMS) { IItemHandler handler = LevelUtils.getItemHandler( level, pos.relative(getDirection()), getDirection().getOpposite() ); if (handler != null) { while (filterSlot + 1 < itemFilters.getSlots() && itemFilters.getStackInSlot(filterSlot).isEmpty()) { filterSlot++; } // We jump out of the loop above if we reach the maximum slot. If the maximum slot is empty, // we waste a tick with doing nothing because it's empty. Hence this check. If we are at the last slot // and it's empty, go back to slot 0. // We also handle if we exceeded the maximum slot in general. if ((filterSlot == itemFilters.getSlots() - 1 && itemFilters.getStackInSlot(filterSlot).isEmpty()) || (filterSlot >= itemFilters.getSlots())) { filterSlot = 0; } ItemStack slot = itemFilters.getStackInSlot(filterSlot); if (!slot.isEmpty()) { int stackSize = upgrades.getStackInteractCount(); if (upgrades.hasUpgrade(UpgradeItem.Type.REGULATOR)) { int found = 0; for (int i = 0; i < handler.getSlots(); i++) { ItemStack stackInConnectedHandler = handler.getStackInSlot(i); if (API.instance().getComparer().isEqual(slot, stackInConnectedHandler, compare)) { found += stackInConnectedHandler.getCount(); } } int needed = 0; for (int i = 0; i < itemFilters.getSlots(); ++i) { if (API.instance().getComparer().isEqualNoQuantity(slot, itemFilters.getStackInSlot(i))) { needed += itemFilters.getStackInSlot(i).getCount(); } } stackSize = Math.min(stackSize, needed - found); } if (stackSize > 0) { ItemStack took = network.extractItem(slot, Math.min(slot.getMaxStackSize(), stackSize), compare, Action.SIMULATE); if (took.isEmpty()) { if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(new SlottedCraftingRequest(this, filterSlot), slot, stackSize); } } else { ItemStack remainder = ItemHandlerHelper.insertItem(handler, took, true); int correctedStackSize = took.getCount() - remainder.getCount(); if (correctedStackSize > 0) { took = network.extractItem(slot, correctedStackSize, compare, Action.PERFORM); ItemHandlerHelper.insertItem(handler, took, false); } } } } filterSlot++; } } else if (type == IType.FLUIDS) { FluidStack[] fluids = fluidFilters.getFluids(); while (filterSlot + 1 < fluids.length && fluids[filterSlot] == null) { filterSlot++; } // We jump out of the loop above if we reach the maximum slot. If the maximum slot is empty, // we waste a tick with doing nothing because it's empty. Hence this check. If we are at the last slot // and it's empty, go back to slot 0. // We also handle if we exceeded the maximum slot in general. if ((filterSlot == fluids.length - 1 && fluids[filterSlot] == null) || (filterSlot >= fluids.length)) { filterSlot = 0; } IFluidHandler handler = LevelUtils.getFluidHandler( level, pos.relative(getDirection()), getDirection().getOpposite() ); if (handler != null) { FluidStack stack = fluids[filterSlot]; if (stack != null) { int toExtract = FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount(); FluidStack stackInStorage = network.getFluidStorageCache().getList().get(stack, compare); if (stackInStorage != null) { toExtract = Math.min(toExtract, stackInStorage.getAmount()); if (upgrades.hasUpgrade(UpgradeItem.Type.REGULATOR)) { int found = 0; for (int i = 0; i < handler.getTanks(); i++) { FluidStack stackInConnectedHandler = handler.getFluidInTank(i); if (API.instance().getComparer().isEqual(stack, stackInConnectedHandler, compare)) { found += stackInConnectedHandler.getAmount(); } } int needed = 0; for (int i = 0; i < fluidFilters.getSlots(); ++i) { if (API.instance().getComparer().isEqual(stack, fluidFilters.getFluid(i), IComparer.COMPARE_NBT)) { needed += fluidFilters.getFluid(i).getAmount(); } } toExtract = Math.min(toExtract, needed - found); } if (toExtract > 0) { FluidStack took = network.extractFluid(stack, toExtract, compare, Action.SIMULATE); int filled = handler.fill(took, IFluidHandler.FluidAction.SIMULATE); if (filled > 0) { took = network.extractFluid(stack, filled, compare, Action.PERFORM); handler.fill(took, IFluidHandler.FluidAction.EXECUTE); } } } else if (upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(this, stack, toExtract); } } filterSlot++; } } } } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); StackUtils.writeItems(upgrades, 1, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_TYPE, type); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } StackUtils.readItems(upgrades, 1, tag); } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } public UpgradeItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return getUpgrades(); } @Override public int getType() { return level.isClientSide ? ExporterBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } @Override public CoverManager getCoverManager() { return coverManager; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ExternalStorageNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.*; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class ExternalStorageNetworkNode extends NetworkNode implements IStorageProvider, IStorageScreen, IComparable, IWhitelistBlacklist, IPrioritizable, IType, IAccessType, IExternalStorageContext, ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "external_storage"); private static final Logger LOGGER = LogManager.getLogger(ExternalStorageNetworkNode.class); private static final String NBT_PRIORITY = "Priority"; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final List> itemStorages = new CopyOnWriteArrayList<>(); private final List> fluidStorages = new CopyOnWriteArrayList<>(); private final CoverManager coverManager; private int priority = 0; private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private int type = IType.ITEMS; private AccessType accessType = AccessType.INSERT_EXTRACT; private int networkTicks; public ExternalStorageNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getExternalStorage().getUsage(); } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); LOGGER.debug("Connectivity state of external storage at {} changed to {} due to {}", pos, state, cause); updateStorage(network, InvalidateCause.CONNECTED_STATE_CHANGED); } @Override public void update() { super.update(); if (canUpdate() && level.isLoaded(pos)) { if (networkTicks++ == 0) { updateStorage(network, InvalidateCause.INITIAL_TICK_INVALIDATION); return; } for (IExternalStorage storage : itemStorages) { storage.update(network); } for (IExternalStorage storage : fluidStorages) { storage.update(network); } } } @Override public void onDirectionChanged(Direction direction) { super.onDirectionChanged(direction); if (network != null) { updateStorage(network, InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); tag.putInt(NBT_PRIORITY, priority); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_TYPE, type); AccessTypeUtils.writeAccessType(tag, accessType); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } if (tag.contains(NBT_PRIORITY)) { priority = tag.getInt(NBT_PRIORITY); } if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } accessType = AccessTypeUtils.readAccessType(tag); } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } @Override public int getPriority() { return priority; } @Override public void setPriority(int priority) { this.priority = priority; markDirty(); if (network != null) { network.getItemStorageCache().sort(); network.getFluidStorageCache().sort(); } } public void updateStorage(INetwork network, InvalidateCause cause) { itemStorages.clear(); fluidStorages.clear(); BlockEntity facing = getFacingBlockEntity(); if (facing != null) { if (type == IType.ITEMS) { for (IExternalStorageProvider provider : API.instance().getExternalStorageProviders(StorageType.ITEM)) { if (provider.canProvide(level, pos.relative(getDirection()), getDirection())) { itemStorages.add(provider.provide(this, getFacingBlockEntity(), getDirection())); break; } } } else if (type == IType.FLUIDS) { for (IExternalStorageProvider provider : API.instance().getExternalStorageProviders(StorageType.FLUID)) { if (provider.canProvide(level, pos.relative(getDirection()), getDirection())) { fluidStorages.add(provider.provide(this, getFacingBlockEntity(), getDirection())); break; } } } } network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(cause)); network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(cause)); } @Override public void addItemStorages(List> storages) { storages.addAll(this.itemStorages); } @Override public void addFluidStorages(List> storages) { storages.addAll(this.fluidStorages); } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage:external_storage"); } @Override public long getStored() { return ExternalStorageBlockEntity.STORED.getValue(); } @Override public long getCapacity() { return ExternalStorageBlockEntity.CAPACITY.getValue(); } @Override public AccessType getAccessType() { return accessType; } @Override public void setAccessType(AccessType type) { this.accessType = type; if (network != null) { network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } markDirty(); } @Override public boolean acceptsItem(ItemStack stack) { return IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, stack); } @Override public boolean acceptsFluid(FluidStack stack) { return IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, stack); } @Override public int getType() { return level.isClientSide ? ExternalStorageBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); if (network != null) { updateStorage(network, InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } public List> getItemStorages() { return itemStorages; } public List> getFluidStorages() { return fluidStorages; } @Override public CoverManager getCoverManager() { return coverManager; } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/FluidInterfaceNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorage; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.fluid.ProxyFluidHandler; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.templates.FluidTank; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; import org.apache.commons.lang3.tuple.Pair; public class FluidInterfaceNetworkNode extends NetworkNode { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "fluid_interface"); public static final int TANK_CAPACITY = 16_000; private static final String NBT_TANK_IN = "TankIn"; private static final String NBT_TANK_OUT = "TankOut"; private static final String NBT_OUT = "Out"; private final FluidTank tankIn = new FluidTank(TANK_CAPACITY) { @Override protected void onContentsChanged() { super.onContentsChanged(); if (!level.isClientSide && level.isLoaded(pos)) { ((FluidInterfaceBlockEntity) level.getBlockEntity(pos)).getDataManager().sendParameterToWatchers(FluidInterfaceBlockEntity.TANK_IN); } markDirty(); } }; private final FluidTank tankOut = new FluidTank(TANK_CAPACITY); private final ProxyFluidHandler tank = new ProxyFluidHandler(tankIn, tankOut); private final BaseItemHandler in = new BaseItemHandler(1).addListener(new NetworkNodeInventoryListener(this)).addValidator(stack -> !StackUtils.getFluid(stack, true).getValue().isEmpty()); private final FluidInventory out = new FluidInventory(1, TANK_CAPACITY).addListener(new NetworkNodeFluidInventoryListener(this)); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK, UpgradeItem.Type.CRAFTING).addListener(new NetworkNodeInventoryListener(this)); public FluidInterfaceNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public void update() { super.update(); if (canUpdate()) { ItemStack container = in.getStackInSlot(0); if (!container.isEmpty()) { Pair result = StackUtils.getFluid(container, true); if (!result.getValue().isEmpty() && tankIn.fill(result.getValue(), IFluidHandler.FluidAction.SIMULATE) == result.getValue().getAmount()) { result = StackUtils.getFluid(container, false); tankIn.fill(result.getValue(), IFluidHandler.FluidAction.EXECUTE); in.setStackInSlot(0, result.getLeft()); } } if (ticks % upgrades.getSpeed() == 0) { FluidStack drained = tankIn.drain(FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount(), IFluidHandler.FluidAction.EXECUTE); // Drain in tank if (!drained.isEmpty()) { FluidStack remainder = network.insertFluidTracked(drained, drained.getAmount()); tankIn.fill(remainder, IFluidHandler.FluidAction.EXECUTE); } } FluidStack wanted = out.getFluid(0); FluidStack got = tankOut.getFluid(); if (wanted.isEmpty()) { if (!got.isEmpty()) { tankOut.setFluid(network.insertFluidTracked(got, got.getAmount())); onTankOutChanged(); } } else if (!got.isEmpty() && !API.instance().getComparer().isEqual(wanted, got, IComparer.COMPARE_NBT)) { tankOut.setFluid(network.insertFluidTracked(got, got.getAmount())); onTankOutChanged(); } else { int delta = got.isEmpty() ? wanted.getAmount() : (wanted.getAmount() - got.getAmount()); if (delta > 0) { final boolean actingAsStorage = isActingAsStorage(); FluidStack result = network.extractFluid(wanted, delta, IComparer.COMPARE_NBT, Action.PERFORM, s -> { // If we are not an interface acting as a storage, we can extract from anywhere. if (!actingAsStorage) { return true; } // If we are an interface acting as a storage, we don't want to extract from other interfaces to // avoid stealing from each other. return !(s instanceof FluidExternalStorage) || !((FluidExternalStorage) s).isConnectedToInterface(); }); if (!result.isEmpty()) { if (tankOut.getFluid().isEmpty()) { tankOut.setFluid(result); } else { tankOut.getFluid().grow(result.getAmount()); } onTankOutChanged(); } // Example: our delta is 5, we extracted 3 fluids. // That means we still have to autocraft 2 fluids. delta -= result.getAmount(); if (delta > 0 && upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(this, wanted, delta); } } else if (delta < 0) { FluidStack remainder = network.insertFluidTracked(got, Math.abs(delta)); tankOut.getFluid().shrink(Math.abs(delta) - remainder.getAmount()); onTankOutChanged(); } } } } private boolean isActingAsStorage() { for (Direction facing : Direction.values()) { INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(facing)); if (facingNode instanceof ExternalStorageNetworkNode && facingNode.isActive() && ((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() && ((ExternalStorageNetworkNode) facingNode).getType() == IType.FLUIDS) { return true; } } return false; } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getFluidInterface().getUsage(); } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(upgrades, 0, tag); StackUtils.writeItems(in, 1, tag); tag.put(NBT_TANK_IN, tankIn.writeToNBT(new CompoundTag())); tag.put(NBT_TANK_OUT, tankOut.writeToNBT(new CompoundTag())); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(upgrades, 0, tag); StackUtils.readItems(in, 1, tag); if (tag.contains(NBT_TANK_IN)) { tankIn.readFromNBT(tag.getCompound(NBT_TANK_IN)); } if (tag.contains(NBT_TANK_OUT)) { tankOut.readFromNBT(tag.getCompound(NBT_TANK_OUT)); } } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.put(NBT_OUT, out.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_OUT)) { out.readFromNbt(tag.getCompound(NBT_OUT)); } } public UpgradeItemHandler getUpgrades() { return upgrades; } public BaseItemHandler getIn() { return in; } public FluidInventory getOut() { return out; } public ProxyFluidHandler getTank() { return tank; } public FluidTank getTankIn() { return tankIn; } public FluidTank getTankOut() { return tankOut; } private void onTankOutChanged() { if (!level.isClientSide && level.isLoaded(pos)) { ((FluidInterfaceBlockEntity) level.getBlockEntity(pos)).getDataManager().sendParameterToWatchers(FluidInterfaceBlockEntity.TANK_OUT); } markDirty(); } @Override public IItemHandler getDrops() { return new CombinedInvWrapper(in, upgrades); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/GridNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.network.grid.*; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.ItemGridStorageCacheListener; import com.refinedmods.refinedstorage.block.GridBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.*; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingRecipe; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; import net.neoforged.neoforge.items.wrapper.InvWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class GridNetworkNode extends NetworkNode implements INetworkAwareGrid, IType { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid"); public static final ResourceLocation CRAFTING_ID = new ResourceLocation(RS.ID, "crafting_grid"); public static final ResourceLocation PATTERN_ID = new ResourceLocation(RS.ID, "pattern_grid"); public static final ResourceLocation FLUID_ID = new ResourceLocation(RS.ID, "fluid_grid"); public static final String NBT_VIEW_TYPE = "ViewType"; public static final String NBT_SORTING_DIRECTION = "SortingDirection"; public static final String NBT_SORTING_TYPE = "SortingType"; public static final String NBT_SEARCH_BOX_MODE = "SearchBoxMode"; public static final String NBT_TAB_SELECTED = "TabSelected"; public static final String NBT_TAB_PAGE = "TabPage"; public static final String NBT_SIZE = "Size"; public static final int PROCESSING_MATRIX_SIZE = 81; private static final String NBT_EXACT_MODE = "Exact"; private static final String NBT_PROCESSING_PATTERN = "ProcessingPattern"; private static final String NBT_PROCESSING_TYPE = "ProcessingType"; private static final String NBT_PROCESSING_MATRIX_FLUIDS = "ProcessingMatrixFluids"; private static final String NBT_ALLOWED_TAGS = "AllowedTags"; private final AllowedTagList allowedTagList = new AllowedTagList(this::updateAllowedTags, PROCESSING_MATRIX_SIZE); private final ResultContainer result = new ResultContainer(); private final BaseItemHandler processingMatrix = new BaseItemHandler(PROCESSING_MATRIX_SIZE * 2) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!reading && slot < PROCESSING_MATRIX_SIZE) { allowedTagList.clearItemTags(slot); } }); private final AbstractContainerMenu craftingContainer = new AbstractContainerMenu(MenuType.CRAFTING, 0) { @Override public boolean stillValid(Player player) { return false; } @Override public ItemStack quickMoveStack(Player p_38941_, int p_38942_) { return ItemStack.EMPTY; } @Override public void slotsChanged(Container inventory) { if (!level.isClientSide) { onCraftingMatrixChanged(); } } }; private final FluidInventory processingMatrixFluids = new FluidInventory(PROCESSING_MATRIX_SIZE * 2, FluidType.BUCKET_VOLUME * 64) .addListener(new NetworkNodeFluidInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!reading && slot < PROCESSING_MATRIX_SIZE) { allowedTagList.clearFluidTags(slot); } }); private final Set craftingListeners = new HashSet<>(); private final List filters = new ArrayList<>(); private final CraftingContainer matrix = new TransientCraftingContainer(craftingContainer, 3, 3); private final List tabs = new ArrayList<>(); private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs).addListener(new NetworkNodeInventoryListener(this)); private final GridType type; private CraftingRecipe currentRecipe; private boolean readingInventory; private int viewType = VIEW_TYPE_NORMAL; private int sortingDirection = SORTING_DIRECTION_DESCENDING; private final BaseItemHandler patterns = new BaseItemHandler(2) { @Override public int getSlotLimit(int slot) { return slot == 1 ? 1 : super.getSlotLimit(slot); } @Nonnull @Override public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { // Allow in slot 0 // Disallow in slot 1 // Only allow in slot 1 when it isn't a blank pattern // This makes it so that written patterns can be re-inserted in slot 1 to be overwritten again // This makes it so that blank patterns can't be inserted in slot 1 through hoppers. if (slot == 0 || stack.getTag() != null) { return super.insertItem(slot, stack, simulate); } return stack; } } .addValidator(new ItemValidator(RSItems.PATTERN.get())) .addListener(new NetworkNodeInventoryListener(this)) .addListener(((handler, slot, reading) -> { ItemStack pattern = handler.getStackInSlot(slot); if (!reading && slot == 1 && !pattern.isEmpty()) { boolean processing = PatternItem.isProcessing(pattern); if (processing) { for (int i = 0; i < PROCESSING_MATRIX_SIZE; ++i) { processingMatrix.setStackInSlot(i, PatternItem.getInputSlot(pattern, i)); processingMatrixFluids.setFluid(i, PatternItem.getFluidInputSlot(pattern, i)); processingMatrix.setStackInSlot(PROCESSING_MATRIX_SIZE + i, PatternItem.getOutputSlot(pattern, i)); processingMatrixFluids.setFluid(PROCESSING_MATRIX_SIZE + i, PatternItem.getFluidOutputSlot(pattern, i)); } AllowedTagList allowedTagsFromPattern = PatternItem.getAllowedTags(pattern); if (allowedTagsFromPattern != null) { allowedTagList.setAllowedItemTags(allowedTagsFromPattern.getAllowedItemTags()); allowedTagList.setAllowedFluidTags(allowedTagsFromPattern.getAllowedFluidTags()); } } else { for (int i = 0; i < 9; ++i) { matrix.setItem(i, PatternItem.getInputSlot(pattern, i)); } } setProcessingPattern(processing); markDirty(); } })); private int sortingType = SORTING_TYPE_QUANTITY; private int searchBoxMode = SEARCH_BOX_MODE_NORMAL; private int size = SIZE_STRETCH; private int tabSelected = -1; private int tabPage = 0; private boolean exactPattern = true; private boolean processingPattern = false; private int processingType = IType.ITEMS; public GridNetworkNode(Level level, BlockPos pos, GridType type) { super(level, pos); this.type = type; } public static ResourceLocation getId(GridType type) { switch (type) { case NORMAL: return ID; case CRAFTING: return CRAFTING_ID; case PATTERN: return PATTERN_ID; case FLUID: return FLUID_ID; default: throw new IllegalArgumentException("Unknown grid type " + type); } } public AllowedTagList getAllowedTagList() { return allowedTagList; } private void updateAllowedTags() { markDirty(); BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof GridBlockEntity) { ((GridBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(GridBlockEntity.ALLOWED_ITEM_TAGS); ((GridBlockEntity) blockEntity).getDataManager().sendParameterToWatchers(GridBlockEntity.ALLOWED_FLUID_TAGS); } } @Override public int getEnergyUsage() { switch (type) { case NORMAL: return RS.SERVER_CONFIG.getGrid().getGridUsage(); case CRAFTING: return RS.SERVER_CONFIG.getGrid().getCraftingGridUsage(); case PATTERN: return RS.SERVER_CONFIG.getGrid().getPatternGridUsage(); case FLUID: return RS.SERVER_CONFIG.getGrid().getFluidGridUsage(); default: return 0; } } public boolean isExactPattern() { return exactPattern; } public void setExactPattern(boolean exactPattern) { this.exactPattern = exactPattern; } public boolean isProcessingPattern() { return level.isClientSide ? GridBlockEntity.PROCESSING_PATTERN.getValue() : processingPattern; } public void setProcessingPattern(boolean processingPattern) { this.processingPattern = processingPattern; } @Override public GridType getGridType() { return type; } @Override public IStorageCacheListener createListener(ServerPlayer player) { return type == GridType.FLUID ? new FluidGridStorageCacheListener(player, network) : new ItemGridStorageCacheListener(player, network); } @Nullable @Override public IStorageCache getStorageCache() { if (network != null) { return type == GridType.FLUID ? network.getFluidStorageCache() : network.getItemStorageCache(); } return null; } @Nullable @Override public IItemGridHandler getItemHandler() { return network != null ? network.getItemGridHandler() : null; } @Nullable @Override public IFluidGridHandler getFluidHandler() { return network != null ? network.getFluidGridHandler() : null; } @Override public void addCraftingListener(ICraftingGridListener listener) { craftingListeners.add(listener); } @Override public void removeCraftingListener(ICraftingGridListener listener) { craftingListeners.remove(listener); } @Override public Component getTitle() { switch (type) { case CRAFTING: return Component.translatable("gui.refinedstorage.crafting_grid"); case PATTERN: return Component.translatable("gui.refinedstorage.pattern_grid"); case FLUID: return Component.translatable("gui.refinedstorage.fluid_grid"); default: return Component.translatable("gui.refinedstorage.grid"); } } public IItemHandler getPatterns() { return patterns; } @Override public IItemHandlerModifiable getFilter() { return filter; } @Override public List getFilters() { return filters; } @Override public List getTabs() { return tabs; } @Override public CraftingContainer getCraftingMatrix() { return matrix; } @Override public ResultContainer getCraftingResult() { return result; } public BaseItemHandler getProcessingMatrix() { return processingMatrix; } public FluidInventory getProcessingMatrixFluids() { return processingMatrixFluids; } @Override public void onCraftingMatrixChanged() { if (currentRecipe == null || !currentRecipe.matches(matrix, level)) { currentRecipe = level.getRecipeManager().getRecipeFor(RecipeType.CRAFTING, matrix, level) .map(RecipeHolder::value) .orElse(null); } if (currentRecipe == null) { result.setItem(0, ItemStack.EMPTY); } else { result.setItem(0, currentRecipe.assemble(matrix, level.registryAccess())); } craftingListeners.forEach(ICraftingGridListener::onCraftingMatrixChanged); if (!readingInventory) { markDirty(); } } @Override public void onRecipeTransfer(Player player, ItemStack[][] recipe) { API.instance().getCraftingGridBehavior().onRecipeTransfer(this, player, recipe); } public void clearMatrix() { for (int i = 0; i < processingMatrix.getSlots(); ++i) { processingMatrix.setStackInSlot(i, ItemStack.EMPTY); } for (int i = 0; i < processingMatrixFluids.getSlots(); ++i) { processingMatrixFluids.setFluid(i, FluidStack.EMPTY); } for (int i = 0; i < matrix.getContainerSize(); ++i) { matrix.setItem(i, ItemStack.EMPTY); } } @Override public void onClosed(Player player) { // NO OP } @Override public boolean isGridActive() { BlockState state = level.getBlockState(pos); if (state.getBlock() instanceof GridBlock) { return state.getValue(NetworkNodeBlock.CONNECTED); } return false; } @Override public int getSlotId() { return -1; } @Override public void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { API.instance().getCraftingGridBehavior().onCrafted(this, currentRecipe, player, availableItems, usedItems); } @Override public void onClear(Player player) { if (type == GridType.CRAFTING) { if (network != null && network.canRun() && network.getSecurityManager().hasPermission(Permission.INSERT, player)) { for (int i = 0; i < matrix.getContainerSize(); ++i) { ItemStack slot = matrix.getItem(i); if (!slot.isEmpty()) { matrix.setItem(i, network.insertItem(slot, slot.getCount(), Action.PERFORM)); network.getItemStorageTracker().changed(player, slot.copy()); } } } else { for (int i = 0; i < matrix.getContainerSize(); i++) { ItemStack slot = matrix.getItem(i); if (!slot.isEmpty()) { player.getInventory().add(matrix.getItem(i)); } onCraftingMatrixChanged(); } } } else if (type == GridType.PATTERN) { clearMatrix(); } } @Override public void onCraftedShift(Player player) { API.instance().getCraftingGridBehavior().onCraftedShift(this, player); } public void onCreatePattern() { if (canCreatePattern()) { if (patterns.getStackInSlot(1).isEmpty()) { patterns.extractItem(0, 1, false); } ItemStack pattern = new ItemStack(RSItems.PATTERN.get()); PatternItem.setToCurrentVersion(pattern); PatternItem.setProcessing(pattern, processingPattern); if (!processingPattern) { PatternItem.setExact(pattern, exactPattern); } else { PatternItem.setAllowedTags(pattern, allowedTagList); } if (processingPattern) { for (int i = 0; i < processingMatrix.getSlots(); ++i) { if (!processingMatrix.getStackInSlot(i).isEmpty()) { if (i >= PROCESSING_MATRIX_SIZE) { PatternItem.setOutputSlot(pattern, i - PROCESSING_MATRIX_SIZE, processingMatrix.getStackInSlot(i)); } else { PatternItem.setInputSlot(pattern, i, processingMatrix.getStackInSlot(i)); } } FluidStack fluid = processingMatrixFluids.getFluid(i); if (!fluid.isEmpty()) { if (i >= PROCESSING_MATRIX_SIZE) { PatternItem.setFluidOutputSlot(pattern, i - PROCESSING_MATRIX_SIZE, fluid); } else { PatternItem.setFluidInputSlot(pattern, i, fluid); } } } } else { for (int i = 0; i < 9; ++i) { ItemStack ingredient = matrix.getItem(i); if (!ingredient.isEmpty()) { PatternItem.setInputSlot(pattern, i, ingredient); } } } patterns.setStackInSlot(1, pattern); } } private boolean isPatternAvailable() { return !(patterns.getStackInSlot(0).isEmpty() && patterns.getStackInSlot(1).isEmpty()); } public boolean canCreatePattern() { if (!isPatternAvailable()) { return false; } if (isProcessingPattern()) { int inputsFilled = 0; int outputsFilled = 0; for (int i = 0; i < PROCESSING_MATRIX_SIZE; ++i) { if (!processingMatrix.getStackInSlot(i).isEmpty()) { inputsFilled++; } if (!processingMatrixFluids.getFluid(i).isEmpty()) { inputsFilled++; } } for (int i = PROCESSING_MATRIX_SIZE; i < processingMatrix.getSlots(); ++i) { if (!processingMatrix.getStackInSlot(i).isEmpty()) { outputsFilled++; } if (!processingMatrixFluids.getFluid(i).isEmpty()) { outputsFilled++; } } return inputsFilled > 0 && outputsFilled > 0; } else { return !result.getItem(0).isEmpty() && isPatternAvailable(); } } @Override public int getViewType() { return level.isClientSide ? GridBlockEntity.VIEW_TYPE.getValue() : viewType; } public void setViewType(int viewType) { this.viewType = viewType; } @Override public int getSortingDirection() { return level.isClientSide ? GridBlockEntity.SORTING_DIRECTION.getValue() : sortingDirection; } public void setSortingDirection(int sortingDirection) { this.sortingDirection = sortingDirection; } @Override public int getSortingType() { return level.isClientSide ? GridBlockEntity.SORTING_TYPE.getValue() : sortingType; } public void setSortingType(int sortingType) { this.sortingType = sortingType; } @Override public int getSearchBoxMode() { return level.isClientSide ? GridBlockEntity.SEARCH_BOX_MODE.getValue() : searchBoxMode; } public void setSearchBoxMode(int searchBoxMode) { this.searchBoxMode = searchBoxMode; } @Override public int getSize() { return level.isClientSide ? GridBlockEntity.SIZE.getValue() : size; } public void setSize(int size) { this.size = size; } @Override public int getTabSelected() { return level.isClientSide ? GridBlockEntity.TAB_SELECTED.getValue() : tabSelected; } public void setTabSelected(int tabSelected) { this.tabSelected = tabSelected; } @Override public int getTabPage() { return level.isClientSide ? GridBlockEntity.TAB_PAGE.getValue() : Math.min(tabPage, getTotalTabPages()); } public void setTabPage(int page) { this.tabPage = page; } @Override public int getTotalTabPages() { return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE); } @Override public void onViewTypeChanged(int type) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.VIEW_TYPE, type); } @Override public void onSortingTypeChanged(int type) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SORTING_TYPE, type); } @Override public void onSortingDirectionChanged(int direction) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SORTING_DIRECTION, direction); } @Override public void onSearchBoxModeChanged(int searchBoxMode) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SEARCH_BOX_MODE, searchBoxMode); } @Override public void onSizeChanged(int size) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.SIZE, size); } @Override public void onTabSelectionChanged(int tab) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.TAB_SELECTED, tab); } @Override public void onTabPageChanged(int page) { if (page >= 0 && page <= getTotalTabPages()) { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.TAB_PAGE, page); } } @Override public int getType() { return level.isClientSide ? GridBlockEntity.PROCESSING_TYPE.getValue() : processingType; } @Override public void setType(int type) { this.processingType = type; this.markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return getProcessingMatrix(); } @Override public FluidInventory getFluidFilters() { return getProcessingMatrixFluids(); } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(NBT_ALLOWED_TAGS)) { allowedTagList.readFromNbt(tag.getCompound(NBT_ALLOWED_TAGS)); } readingInventory = true; StackUtils.readItems(matrix, 0, tag); StackUtils.readItems(patterns, 1, tag); StackUtils.readItems(filter, 2, tag); StackUtils.readItems(processingMatrix, 3, tag); if (tag.contains(NBT_PROCESSING_MATRIX_FLUIDS)) { processingMatrixFluids.readFromNbt(tag.getCompound(NBT_PROCESSING_MATRIX_FLUIDS)); } if (tag.contains(NBT_TAB_SELECTED)) { tabSelected = tag.getInt(NBT_TAB_SELECTED); } if (tag.contains(NBT_TAB_PAGE)) { tabPage = tag.getInt(NBT_TAB_PAGE); } readingInventory = false; } @Override public ResourceLocation getId() { return getId(type); } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(NBT_ALLOWED_TAGS, allowedTagList.writeToNbt()); StackUtils.writeItems(matrix, 0, tag); StackUtils.writeItems(patterns, 1, tag); StackUtils.writeItems(filter, 2, tag); StackUtils.writeItems(processingMatrix, 3, tag); tag.put(NBT_PROCESSING_MATRIX_FLUIDS, processingMatrixFluids.writeToNbt()); tag.putInt(NBT_TAB_SELECTED, tabSelected); tag.putInt(NBT_TAB_PAGE, tabPage); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_VIEW_TYPE, viewType); tag.putInt(NBT_SORTING_DIRECTION, sortingDirection); tag.putInt(NBT_SORTING_TYPE, sortingType); tag.putInt(NBT_SEARCH_BOX_MODE, searchBoxMode); tag.putInt(NBT_SIZE, size); tag.putBoolean(NBT_EXACT_MODE, exactPattern); tag.putBoolean(NBT_PROCESSING_PATTERN, processingPattern); tag.putInt(NBT_PROCESSING_TYPE, processingType); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_VIEW_TYPE)) { viewType = tag.getInt(NBT_VIEW_TYPE); } if (tag.contains(NBT_SORTING_DIRECTION)) { sortingDirection = tag.getInt(NBT_SORTING_DIRECTION); } if (tag.contains(NBT_SORTING_TYPE)) { sortingType = tag.getInt(NBT_SORTING_TYPE); } if (tag.contains(NBT_SEARCH_BOX_MODE)) { searchBoxMode = tag.getInt(NBT_SEARCH_BOX_MODE); } if (tag.contains(NBT_SIZE)) { size = tag.getInt(NBT_SIZE); } if (tag.contains(NBT_EXACT_MODE)) { exactPattern = tag.getBoolean(NBT_EXACT_MODE); } if (tag.contains(NBT_PROCESSING_PATTERN)) { processingPattern = tag.getBoolean(NBT_PROCESSING_PATTERN); } if (tag.contains(NBT_PROCESSING_TYPE)) { processingType = tag.getInt(NBT_PROCESSING_TYPE); } } @Override public IItemHandler getDrops() { switch (type) { case CRAFTING: return new CombinedInvWrapper(filter, new InvWrapper(matrix)); case PATTERN: return new CombinedInvWrapper(filter, patterns); default: return new CombinedInvWrapper(filter); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/IStorageScreen.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import net.minecraft.network.chat.Component; public interface IStorageScreen { Component getTitle(); long getStored(); long getCapacity(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/ImporterNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; public class ImporterNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, ICoverable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "importer"); private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FLuidFilters"; private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK).addListener(new NetworkNodeInventoryListener(this)); private final CoverManager coverManager; private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private int type = IType.ITEMS; private int currentSlot; public ImporterNetworkNode(Level level, BlockPos pos) { super(level, pos); this.coverManager = new CoverManager(this); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getImporter().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (!canUpdate() || !level.isLoaded(pos)) { return; } if (type == IType.ITEMS) { BlockEntity facing = getFacingBlockEntity(); IItemHandler handler = LevelUtils.getItemHandler( level, pos.relative(getDirection()), getDirection().getOpposite() ); if (facing instanceof DiskDriveBlockEntity || handler == null) { return; } if (currentSlot >= handler.getSlots()) { currentSlot = 0; } if (handler.getSlots() > 0) { while (currentSlot + 1 < handler.getSlots() && handler.getStackInSlot(currentSlot).isEmpty()) { currentSlot++; } ItemStack stack = handler.getStackInSlot(currentSlot); if (!IWhitelistBlacklist.acceptsItem(itemFilters, mode, compare, stack)) { currentSlot++; } else if (ticks % upgrades.getSpeed() == 0) { ItemStack result = handler.extractItem(currentSlot, upgrades.getStackInteractCount(), true); if (!result.isEmpty() && network.insertItem(result, result.getCount(), Action.SIMULATE).isEmpty()) { result = handler.extractItem(currentSlot, upgrades.getStackInteractCount(), false); network.insertItemTracked(result, result.getCount()); } else { currentSlot++; } } } } else if (type == IType.FLUIDS && ticks % upgrades.getSpeed() == 0) { IFluidHandler handler = LevelUtils.getFluidHandler( level, pos.relative(getDirection()), getDirection().getOpposite() ); if (handler != null) { FluidStack extractedSimulated = handler.drain(FluidType.BUCKET_VOLUME * upgrades.getStackInteractCount(), IFluidHandler.FluidAction.SIMULATE); if (!extractedSimulated.isEmpty() && IWhitelistBlacklist.acceptsFluid(fluidFilters, mode, compare, extractedSimulated) && network.insertFluid(extractedSimulated, extractedSimulated.getAmount(), Action.SIMULATE).isEmpty()) { FluidStack extracted = handler.drain(extractedSimulated, IFluidHandler.FluidAction.EXECUTE); if (!extracted.isEmpty()) { network.insertFluidTracked(extracted, extracted.getAmount()); } } } } } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.contains(CoverManager.NBT_COVER_MANAGER)) { this.coverManager.readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); } StackUtils.readItems(upgrades, 1, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.coverManager.writeToNbt()); StackUtils.writeItems(upgrades, 1, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_TYPE, type); StackUtils.writeItems(itemFilters, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } StackUtils.readItems(itemFilters, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } public IItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return getUpgrades(); } @Override public int getType() { return level.isClientSide ? ImporterBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } @Override public CoverManager getCoverManager() { return coverManager; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/InterfaceNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.ItemExternalStorage; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.ProxyItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; public class InterfaceNetworkNode extends NetworkNode implements IComparable { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "interface"); private static final String NBT_COMPARE = "Compare"; private final BaseItemHandler importItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final BaseItemHandler exportFilterItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final BaseItemHandler exportItems = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final IItemHandler items = new ProxyItemHandler(importItems, exportItems); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK, UpgradeItem.Type.CRAFTING) .addListener(new NetworkNodeInventoryListener(this)); private int compare = IComparer.COMPARE_NBT; private int currentSlot = 0; public InterfaceNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getInterface().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (!canUpdate()) { return; } if (currentSlot >= importItems.getSlots()) { currentSlot = 0; } ItemStack slot = importItems.getStackInSlot(currentSlot); if (slot.isEmpty()) { currentSlot++; } else if (ticks % upgrades.getSpeed() == 0) { int size = Math.min(slot.getCount(), upgrades.getStackInteractCount()); ItemStack remainder = network.insertItemTracked(slot, size); importItems.extractItem(currentSlot, size - remainder.getCount(), false); } for (int i = 0; i < 9; ++i) { ItemStack wanted = exportFilterItems.getStackInSlot(i); ItemStack got = exportItems.getStackInSlot(i); if (wanted.isEmpty()) { if (!got.isEmpty()) { exportItems.setStackInSlot(i, network.insertItemTracked(got, got.getCount())); } } else if (!got.isEmpty() && !API.instance().getComparer().isEqual(wanted, got, getCompare())) { exportItems.setStackInSlot(i, network.insertItemTracked(got, got.getCount())); } else { int delta = got.isEmpty() ? wanted.getCount() : (wanted.getCount() - got.getCount()); if (delta > 0) { final boolean actingAsStorage = isActingAsStorage(); ItemStack result = network.extractItem(wanted, delta, compare, Action.PERFORM, s -> { // If we are not an interface acting as a storage, we can extract from anywhere. if (!actingAsStorage) { return true; } // If we are an interface acting as a storage, we don't want to extract from other interfaces to // avoid stealing from each other. return !(s instanceof ItemExternalStorage) || !((ItemExternalStorage) s).isConnectedToInterface(); }); if (!result.isEmpty()) { if (exportItems.getStackInSlot(i).isEmpty()) { exportItems.setStackInSlot(i, result); } else { exportItems.getStackInSlot(i).grow(result.getCount()); } } // Example: our delta is 5, we extracted 3 items. // That means we still have to autocraft 2 items. delta -= result.getCount(); if (delta > 0 && upgrades.hasUpgrade(UpgradeItem.Type.CRAFTING)) { network.getCraftingManager().request(new SlottedCraftingRequest(this, i), wanted, delta); } } else if (delta < 0) { ItemStack remainder = network.insertItemTracked(got, Math.abs(delta)); exportItems.extractItem(i, Math.abs(delta) - remainder.getCount(), false); } } } } private boolean isActingAsStorage() { for (Direction facing : Direction.values()) { INetworkNode facingNode = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos.relative(facing)); if (facingNode instanceof ExternalStorageNetworkNode && facingNode.isActive() && ((ExternalStorageNetworkNode) facingNode).getDirection() == facing.getOpposite() && ((ExternalStorageNetworkNode) facingNode).getType() == IType.ITEMS) { return true; } } return false; } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(importItems, 0, tag); StackUtils.readItems(exportItems, 2, tag); StackUtils.readItems(upgrades, 3, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(importItems, 0, tag); StackUtils.writeItems(exportItems, 2, tag); StackUtils.writeItems(upgrades, 3, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); StackUtils.writeItems(exportFilterItems, 1, tag); tag.putInt(NBT_COMPARE, compare); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); StackUtils.readItems(exportFilterItems, 1, tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } } public IItemHandler getImportItems() { return importItems; } public IItemHandler getExportFilterItems() { return exportFilterItems; } public IItemHandler getExportItems() { return exportItems; } public IItemHandler getItems() { return items; } public IItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return new CombinedInvWrapper(importItems, exportItems, upgrades); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.properties.DirectionProperty; import net.neoforged.neoforge.items.IItemHandler; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.UUID; public abstract class NetworkNode implements INetworkNode, INetworkNodeVisitor { private static final Logger LOGGER = LogManager.getLogger(); private static final String NBT_OWNER = "Owner"; private static final String NBT_VERSION = "Version"; private static final int CURRENT_VERSION = 1; @Nullable protected INetwork network; // @Volatile: Mental note. At this moment world instances are retained in Minecraft (since 1.16). // This means that during the entire server lifetime, all worlds are present and will not change their instance. // However, due to the memory footprint of worlds and modded minecraft having the tendency to have lots of worlds, // Forge is planning to unload (aka remove) worlds so their instances will change. // This is problematic as this attribute will target the wrong world in that case. // Idea: possibly change to a getter based on RegistryKey? // Another note: this attribute isn't the *real* problem. Because network nodes are in SavedData in a tick handler, // new instances of network nodes will be created when the world refreshes (causing this field to be different too). // 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, // having multiple different instances of the same network node. protected Level level; protected BlockPos pos; protected int ticks; protected RedstoneMode redstoneMode = RedstoneMode.IGNORE; @Nullable protected UUID owner; protected String version; private boolean redstonePowered = false; private Direction direction; // Disable throttling for the first tick. // This is to make sure couldUpdate is going to be correctly set. // If we place 2 blocks next to each other, and disconnect the first one really fast, // the second one would not realize it has been disconnected because couldUpdate == canUpdate. // It would however still have the connected state, due to the initial block update packet. // The couldUpdate/canUpdate system is separate from that. private boolean throttlingDisabled = true; private boolean couldUpdate; private int ticksSinceUpdateChanged; protected NetworkNode(Level level, BlockPos pos) { if (level == null) { throw new IllegalArgumentException("World cannot be null"); } this.level = level; this.pos = pos; } public RedstoneMode getRedstoneMode() { return redstoneMode; } public void setRedstoneMode(RedstoneMode redstoneMode) { this.redstoneMode = redstoneMode; markDirty(); } @Nonnull @Override public ItemStack getItemStack() { return new ItemStack(Item.BY_BLOCK.get(level.getBlockState(pos).getBlock()), 1); } @Override public void onConnected(INetwork network) { onConnectedStateChange(network, true, ConnectivityStateChangeCause.GRAPH_CHANGE); this.network = network; } @Override public void onDisconnected(INetwork network) { this.network = null; onConnectedStateChange(network, false, ConnectivityStateChangeCause.GRAPH_CHANGE); } protected void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { // NO OP } @Override public void markDirty() { if (!level.isClientSide) { API.instance().getNetworkNodeManager((ServerLevel) level).markForSaving(); } } @Override public boolean isActive() { return redstoneMode.isEnabled(redstonePowered); } protected final boolean canUpdate() { if (isActive() && network != null) { return network.canRun(); } return false; } protected int getUpdateThrottleInactiveToActive() { return 20; } protected int getUpdateThrottleActiveToInactive() { return 4; } public void setRedstonePowered(boolean redstonePowered) { this.redstonePowered = redstonePowered; } @Override public void update() { if (ticks == 0) { redstonePowered = level.hasNeighborSignal(pos); } ++ticks; boolean canUpdate = canUpdate(); if (couldUpdate != canUpdate) { ++ticksSinceUpdateChanged; if ((canUpdate ? (ticksSinceUpdateChanged > getUpdateThrottleInactiveToActive()) : (ticksSinceUpdateChanged > getUpdateThrottleActiveToInactive())) || throttlingDisabled) { ticksSinceUpdateChanged = 0; couldUpdate = canUpdate; throttlingDisabled = false; BlockState blockState = level.getBlockState(pos); if (blockState.getBlock() instanceof NetworkNodeBlock && ((NetworkNodeBlock) blockState.getBlock()).hasConnectedState()) { level.setBlockAndUpdate(pos, level.getBlockState(pos).setValue(NetworkNodeBlock.CONNECTED, canUpdate)); } if (network != null) { onConnectedStateChange(network, canUpdate, ConnectivityStateChangeCause.REDSTONE_MODE_OR_NETWORK_ENERGY_CHANGE); if (shouldRebuildGraphOnChange()) { network.getNodeGraph().invalidate(Action.PERFORM, network.getLevel(), network.getPosition()); } } } } else { ticksSinceUpdateChanged = 0; } } @Override public CompoundTag write(CompoundTag tag) { if (owner != null) { tag.putUUID(NBT_OWNER, owner); } tag.putInt(NBT_VERSION, CURRENT_VERSION); writeConfiguration(tag); return tag; } public CompoundTag writeConfiguration(CompoundTag tag) { redstoneMode.write(tag); return tag; } public void read(CompoundTag tag) { if (tag.hasUUID(NBT_OWNER)) { owner = tag.getUUID(NBT_OWNER); } if (tag.contains(NBT_VERSION)) { version = tag.getString(NBT_VERSION); } readConfiguration(tag); } public void readConfiguration(CompoundTag tag) { redstoneMode = RedstoneMode.read(tag); } @Nullable @Override public INetwork getNetwork() { return network; } @Override public BlockPos getPos() { return pos; } @Override public Level getLevel() { return level; } @Override public boolean canConduct(Direction direction) { return true; } @Override public void visit(Operator operator) { for (Direction facing : Direction.values()) { BlockPos facingPos = pos.relative(facing); if (!level.isLoaded(facingPos)) { continue; } INetworkNode oppositeNode = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(facingPos)); if (oppositeNode == null) { continue; } if (canConduct(facing) && oppositeNode.canReceive(facing.getOpposite())) { operator.apply(level, facingPos, facing.getOpposite()); } } } @Nullable public BlockEntity getFacingBlockEntity() { BlockPos facingPos = pos.relative(getDirection()); if (!level.isLoaded(facingPos)) { return null; } return level.getBlockEntity(facingPos); } public Direction getDirection() { if (direction == null) { BlockState state = level.getBlockState(pos); if (state.getBlock() instanceof BaseBlock baseBlock) { DirectionProperty property = baseBlock.getDirection().getProperty(); if (state.hasProperty(property)) { direction = state.getValue(property); } else { LOGGER.warn("Node @ {} has no direction! Consider recreating the block", pos); return Direction.NORTH; } } } return direction; } public void onDirectionChanged(Direction direction) { this.direction = direction; } @Nullable public IItemHandler getDrops() { return null; } public boolean shouldRebuildGraphOnChange() { return false; } @Override @Nullable public UUID getOwner() { return owner; } @Override public void setOwner(@Nullable UUID owner) { this.owner = owner; markDirty(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkReceiverNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; public class NetworkReceiverNetworkNode extends NetworkNode { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "network_receiver"); public NetworkReceiverNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getNetworkReceiver().getUsage(); } @Override public ResourceLocation getId() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/NetworkTransmitterNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.blockentity.NetworkReceiverBlockEntity; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.NetworkCardItem; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nullable; public class NetworkTransmitterNetworkNode extends NetworkNode { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "network_transmitter"); private BlockPos receiver; private ResourceKey receiverDimension; private final BaseItemHandler networkCard = new BaseItemHandler(1) .addValidator(new ItemValidator(RSItems.NETWORK_CARD.get())) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { ItemStack card = handler.getStackInSlot(slot); if (card.isEmpty()) { receiver = null; receiverDimension = null; } else { receiver = NetworkCardItem.getReceiver(card); receiverDimension = NetworkCardItem.getDimension(card); } if (network != null) { network.getNodeGraph().invalidate(Action.PERFORM, network.getLevel(), network.getPosition()); } }); public NetworkTransmitterNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(networkCard, 0, tag); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(networkCard, 0, tag); } @Override public ResourceLocation getId() { return ID; } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getNetworkTransmitter().getUsage(); } public BaseItemHandler getNetworkCard() { return networkCard; } @Override public IItemHandler getDrops() { return getNetworkCard(); } @Nullable public ResourceKey getReceiverDimension() { return receiverDimension; } public int getDistance() { if (receiver == null || receiverDimension == null || !isSameDimension()) { return -1; } 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)); } public boolean isSameDimension() { return level.dimension() == receiverDimension; } private boolean canTransmit() { return canUpdate() && receiver != null && receiverDimension != null; } @Override public boolean shouldRebuildGraphOnChange() { return true; } @Override public void visit(INetworkNodeVisitor.Operator operator) { super.visit(operator); if (canTransmit()) { if (!isSameDimension()) { Level dimensionLevel = level.getServer().getLevel(receiverDimension); if (dimensionLevel != null && dimensionLevel.isLoaded(receiver) && dimensionLevel.getBlockEntity(receiver) instanceof NetworkReceiverBlockEntity) { operator.apply(dimensionLevel, receiver, null); } } else { if (level.isLoaded(receiver) && level.getBlockEntity(receiver) instanceof NetworkReceiverBlockEntity) { operator.apply(level, receiver, null); } } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/RelayNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; public class RelayNetworkNode extends NetworkNode { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "relay"); public RelayNetworkNode(Level level, BlockPos pos) { super(level, pos); this.redstoneMode = RedstoneMode.LOW; } @Override protected int getUpdateThrottleInactiveToActive() { return 0; } @Override protected int getUpdateThrottleActiveToInactive() { return 0; } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getRelay().getUsage(); } @Override public ResourceLocation getId() { return ID; } @Override public boolean canConduct(Direction direction) { return canUpdate(); } @Override public boolean canReceive(Direction direction) { return true; } @Override public boolean shouldRebuildGraphOnChange() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/RootNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeVisitor; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.UUID; public class RootNetworkNode implements INetworkNode, INetworkNodeVisitor { private final INetwork network; private final Level level; private final BlockPos pos; public RootNetworkNode(INetwork network, Level level, BlockPos pos) { this.network = network; this.level = level; this.pos = pos; } @Override public ResourceLocation getId() { return null; } @Nullable @Override public UUID getOwner() { return null; } @Override public void setOwner(@Nullable UUID owner) { // NO OP } @Override public int getEnergyUsage() { return 0; } @Nonnull @Override public ItemStack getItemStack() { BlockState state = level.getBlockState(pos); @SuppressWarnings("deprecation") Item item = Item.byBlock(state.getBlock()); return new ItemStack(item, 1); } @Override public void onConnected(INetwork network) { // NO OP } @Override public void onDisconnected(INetwork network) { // NO OP } @Override public boolean isActive() { return false; } @Override public INetwork getNetwork() { return network; } @Override public void update() { // NO OP } @Override public CompoundTag write(CompoundTag tag) { return tag; } @Override public BlockPos getPos() { return pos; } @Override public Level getLevel() { return level; } @Override public void markDirty() { // NO OP } @Override public void visit(Operator operator) { for (Direction facing : Direction.values()) { BlockPos relativePos = pos.relative(facing); if (!level.isLoaded(relativePos)) { continue; } operator.apply(level, relativePos, facing.getOpposite()); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/SecurityManagerNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.security.ISecurityCard; import com.refinedmods.refinedstorage.api.network.security.ISecurityCardContainer; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.apiimpl.network.security.SecurityCard; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.SecurityCardItem; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class SecurityManagerNetworkNode extends NetworkNode implements ISecurityCardContainer { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "security_manager"); private final List cards = new ArrayList<>(); private final BaseItemHandler editCard = new BaseItemHandler(1) .addValidator(new ItemValidator(RSItems.SECURITY_CARD.get())) .addListener(new NetworkNodeInventoryListener(this)); private ISecurityCard globalCard; public SecurityManagerNetworkNode(Level level, BlockPos pos) { super(level, pos); } private final BaseItemHandler cardsInv = new BaseItemHandler(9 * 2) .addValidator(new ItemValidator(RSItems.SECURITY_CARD.get())) .addListener(new NetworkNodeInventoryListener(this)) .addListener(((handler, slot, reading) -> { if (!level.isClientSide) { invalidate(); } if (network != null) { network.getSecurityManager().invalidate(); } })); @Override public int getEnergyUsage() { int usage = RS.SERVER_CONFIG.getSecurityManager().getUsage(); for (int i = 0; i < cardsInv.getSlots(); ++i) { if (!cardsInv.getStackInSlot(i).isEmpty()) { usage += RS.SERVER_CONFIG.getSecurityManager().getUsagePerCard(); } } return usage; } @Override public void update() { super.update(); if (ticks == 1) { invalidate(); } } private void invalidate() { this.cards.clear(); this.globalCard = null; for (int i = 0; i < cardsInv.getSlots(); ++i) { ItemStack stack = cardsInv.getStackInSlot(i); if (!stack.isEmpty()) { UUID uuid = SecurityCardItem.getOwner(stack); if (uuid == null) { this.globalCard = createCard(stack, null); continue; } this.cards.add(createCard(stack, uuid)); } } } private ISecurityCard createCard(ItemStack stack, @Nullable UUID uuid) { SecurityCard card = new SecurityCard(uuid); for (Permission permission : Permission.values()) { card.getPermissions().put(permission, SecurityCardItem.hasPermission(stack, permission)); } return card; } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(cardsInv, 0, tag); StackUtils.readItems(editCard, 1, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(cardsInv, 0, tag); StackUtils.writeItems(editCard, 1, tag); return tag; } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); network.getSecurityManager().invalidate(); } public BaseItemHandler getCardsItems() { return cardsInv; } public BaseItemHandler getEditCard() { return editCard; } public void updatePermission(Permission permission, boolean state) { ItemStack card = getEditCard().getStackInSlot(0); if (!card.isEmpty()) { SecurityCardItem.setPermission(card, permission, state); } } @Override public List getCards() { return cards; } @Nullable @Override public ISecurityCard getGlobalCard() { return globalCard; } @Override public IItemHandler getDrops() { return new CombinedInvWrapper(cardsInv, editCard); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/SlottedCraftingRequest.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import java.util.Objects; public class SlottedCraftingRequest { private final INetworkNode node; private final int slot; public SlottedCraftingRequest(INetworkNode node, int slot) { this.node = node; this.slot = slot; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } SlottedCraftingRequest that = (SlottedCraftingRequest) o; return slot == that.slot && Objects.equals(node, that.node); } @Override public int hashCode() { return Objects.hash(node, slot); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/StorageMonitorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.StackUtils; import java.util.HashMap; import java.util.Map; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.Containers; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; import org.apache.commons.lang3.tuple.Pair; public class StorageMonitorNetworkNode extends NetworkNode implements IComparable, IType { public static final int DEPOSIT_ALL_MAX_DELAY = 500; public static final ResourceLocation ID = new ResourceLocation(RS.ID, "storage_monitor"); private static final String NBT_COMPARE = "Compare"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private final BaseItemHandler itemFilter = new BaseItemHandler(1) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!reading) { LevelUtils.updateBlock(level, pos); } }); private final FluidInventory fluidFilter = new FluidInventory(1, FluidType.BUCKET_VOLUME) .addListener((handler, slot, reading) -> { if (!reading) { LevelUtils.updateBlock(level, pos); } }); private final Map> deposits = new HashMap<>(); private int compare = IComparer.COMPARE_NBT; private int type = IType.ITEMS; private int oldAmount = -1; public StorageMonitorNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public void update() { super.update(); if (!canUpdate()) { return; } int newAmount = getAmount(); if (oldAmount == -1) { oldAmount = newAmount; } else if (oldAmount != newAmount) { oldAmount = newAmount; LevelUtils.updateBlock(level, pos); } } public InteractionResult depositAll(Player player) { if (getType() != IType.ITEMS) { return InteractionResult.FAIL; } if (network == null) { return InteractionResult.FAIL; } if (!network.getSecurityManager().hasPermission(Permission.INSERT, player)) { return InteractionResult.FAIL; } Pair deposit = deposits.get(player.getGameProfile().getName()); if (deposit == null) { return InteractionResult.FAIL; } ItemStack inserted = deposit.getKey(); long insertedAt = deposit.getValue(); if (System.currentTimeMillis() - insertedAt < DEPOSIT_ALL_MAX_DELAY) { for (int i = 0; i < player.getInventory().getContainerSize(); ++i) { ItemStack toInsert = player.getInventory().getItem(i); if (API.instance().getComparer().isEqual(inserted, toInsert, compare)) { player.getInventory().setItem(i, network.insertItemTracked(toInsert, toInsert.getCount())); } } } return InteractionResult.SUCCESS; } public InteractionResult deposit(Player player, ItemStack toInsert) { if (network == null) { return InteractionResult.FAIL; } if (!network.getSecurityManager().hasPermission(Permission.INSERT, player)) { return InteractionResult.FAIL; } if (getType() == IType.ITEMS) { depositItems(player, toInsert); } else if (getType() == IType.FLUIDS) { depositFluids(player, toInsert); } return InteractionResult.SUCCESS; } private void depositItems(Player player, ItemStack toInsert) { ItemStack filter = itemFilter.getStackInSlot(0); if (!filter.isEmpty() && API.instance().getComparer().isEqual(filter, toInsert, compare)) { player.getInventory() .setItem(player.getInventory().selected, network.insertItemTracked(toInsert, toInsert.getCount())); deposits.put(player.getGameProfile().getName(), Pair.of(toInsert, System.currentTimeMillis())); } } private void depositFluids(Player player, ItemStack toInsert) { FluidStack filter = fluidFilter.getFluid(0); Pair result = StackUtils.getFluid(toInsert, true); if (filter.isEmpty() || !API.instance().getComparer().isEqual(filter, result.getRight(), compare)) { return; } if (!result.getValue().isEmpty() && network.insertFluid(result.getValue(), result.getValue().getAmount(), Action.SIMULATE).isEmpty()) { network.getFluidStorageTracker().changed(player, result.getValue().copy()); result = StackUtils.getFluid(toInsert, false); network.insertFluidTracked(result.getValue(), result.getValue().getAmount()); player.getInventory().setItem(player.getInventory().selected, ItemStack.EMPTY); ItemStack container = result.getLeft(); if (!player.getInventory().add(container.copy())) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), container); } } } public void extract(Player player, Direction side) { if (network == null || getDirection() != side) { return; } if (!network.getSecurityManager().hasPermission(Permission.EXTRACT, player)) { return; } if (getType() == IType.ITEMS) { extractItems(player); } else if (getType() == IType.FLUIDS) { extractFluids(player); } } private void extractItems(Player player) { ItemStack filter = itemFilter.getStackInSlot(0); int toExtract = player.isCrouching() ? 1 : filter.getMaxStackSize(); if (!filter.isEmpty()) { ItemStack result = network.extractItem(filter, toExtract, compare, Action.PERFORM); if (!result.isEmpty() && !player.getInventory().add(result.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), result); } } } private void extractFluids(Player player) { FluidStack filter = fluidFilter.getFluid(0); if (filter.isEmpty()) { return; } FluidStack stack = network.getFluidStorageCache().getList().get(filter); if (stack == null || stack.getAmount() < FluidType.BUCKET_VOLUME) { return; } boolean shift = player.isCrouching(); if (shift) { NetworkUtils.extractBucketFromPlayerInventoryOrNetwork(player, network, bucket -> { IFluidHandlerItem fluidHandler = bucket.getCapability(Capabilities.FluidHandler.ITEM); if (fluidHandler == null) { return; } network.getFluidStorageTracker().changed(player, stack.copy()); fluidHandler.fill(network.extractFluid(stack, FluidType.BUCKET_VOLUME, Action.PERFORM), IFluidHandler.FluidAction.EXECUTE); if (!player.getInventory().add(fluidHandler.getContainer().copy())) { Containers.dropItemStack(player.getCommandSenderWorld(), player.getX(), player.getY(), player.getZ(), fluidHandler.getContainer()); } }); } } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getStorageMonitor().getUsage(); } @Override public ResourceLocation getId() { return ID; } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; LevelUtils.updateBlock(level, pos); markDirty(); } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_TYPE, type); StackUtils.writeItems(itemFilter, 0, tag); tag.put(NBT_FLUID_FILTERS, fluidFilter.writeToNbt()); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } StackUtils.readItems(itemFilter, 0, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilter.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } } public int getAmount() { if (network == null) { return 0; } if (getType() == IType.ITEMS) { ItemStack toCheck = itemFilter.getStackInSlot(0); if (toCheck.isEmpty()) { return 0; } if (compare == IComparer.COMPARE_NBT) { ItemStack stored = network.getItemStorageCache().getList().get(toCheck, compare); return stored != null ? stored.getCount() : 0; } else { return network.getItemStorageCache().getList().getStacks(toCheck).stream() .mapToInt(entry -> entry.getStack().getCount()).sum(); } } else if (getType() == IType.FLUIDS) { FluidStack toCheck = fluidFilter.getFluid(0); if (toCheck.isEmpty()) { return 0; } FluidStack stored = network.getFluidStorageCache().getList().get(toCheck, compare); return stored != null ? stored.getAmount() : 0; } return 0; } @Override public int getType() { return level.isClientSide ? StorageMonitorBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; LevelUtils.updateBlock(level, pos); markDirty(); } public BaseItemHandler getItemFilters() { return itemFilter; } @Override public FluidInventory getFluidFilters() { return fluidFilter; } @Override public void setRedstoneMode(RedstoneMode mode) { // NO OP } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/WirelessTransmitterNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.IWirelessTransmitter; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandler; public class WirelessTransmitterNetworkNode extends NetworkNode implements IWirelessTransmitter { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_transmitter"); private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.RANGE).addListener(new NetworkNodeInventoryListener(this)); public WirelessTransmitterNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getWirelessTransmitter().getUsage() + upgrades.getEnergyUsage(); } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(upgrades, 0, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(upgrades, 0, tag); return tag; } @Override public int getRange() { return RS.SERVER_CONFIG.getWirelessTransmitter().getBaseRange() + (upgrades.getUpgradeCount(UpgradeItem.Type.RANGE) * RS.SERVER_CONFIG.getWirelessTransmitter().getRangePerUpgrade()); } @Override public BlockPos getOrigin() { return pos; } @Override public ResourceKey getDimension() { return level.dimension(); } public BaseItemHandler getUpgrades() { return upgrades; } @Override public IItemHandler getDrops() { return getUpgrades(); } @Override public boolean canConduct(Direction direction) { return getDirection() == direction; } @Override public void visit(Operator operator) { operator.apply(level, pos.relative(Direction.DOWN), Direction.UP); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/Cover.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.cover; import net.minecraft.world.item.ItemStack; public class Cover { private ItemStack stack; private CoverType type; public Cover(ItemStack stack, CoverType type) { this.stack = stack; this.type = type; } public ItemStack getStack() { return stack; } public CoverType getType() { return type; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/CoverManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.cover; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.item.CoverItem; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.RenderShape; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelProperty; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.ItemStackHandler; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class CoverManager { public static final ModelProperty PROPERTY = new ModelProperty<>(); private static final String NBT_DIRECTION = "Direction"; private static final String NBT_ITEM = "Item"; private static final String NBT_TYPE = "Type"; public static String NBT_COVER_MANAGER = "Cover"; private Map covers = new HashMap<>(); private NetworkNode node; public CoverManager(NetworkNode node) { this.node = node; } @SuppressWarnings("deprecation") public static boolean isValidCover(ItemStack item) { if (item.isEmpty()) { return false; } Block block = getBlock(item); BlockState state = getBlockState(item); return block != null && state != null && isModelSupported(state) && !block.isRandomlyTicking(state) && !(block instanceof EntityBlock) && !state.useShapeForLightOcclusion(); } private static boolean isModelSupported(BlockState state) { if (state.getRenderShape() != RenderShape.MODEL) { return false; } return state.canOcclude(); } @Nullable public static Block getBlock(ItemStack item) { if (item.isEmpty()) { return null; } Block block = Block.byItem(item.getItem()); if (block == Blocks.AIR) { return null; } return block; } @Nullable public static BlockState getBlockState(ItemStack item) { Block block = getBlock(item); if (block == null) { return null; } return block.defaultBlockState(); } @Nullable public Cover getCover(Direction facing) { return covers.get(facing); } public boolean hasCover(Direction facing) { return covers.containsKey(facing); } public boolean setCover(Direction facing, @Nullable Cover cover) { if (cover == null || (isValidCover(cover.getStack()) && !hasCover(facing))) { if (cover != null) { if (!(node instanceof CableNetworkNode) && facing == node.getDirection() && cover.getType() != CoverType.HOLLOW) { return false; } } if (cover == null) { covers.remove(facing); } else { covers.put(facing, cover); } node.markDirty(); if (node.getNetwork() != null) { node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition()); } return true; } return false; } @Nullable public Cover removeCover(Direction direction) { if (hasCover(direction)) { Cover cover = covers.remove(direction); node.markDirty(); if (node.getNetwork() != null) { node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition()); } return cover; } return null; } public void readFromNbt(CompoundTag nbt) { covers.clear(); for (String s : nbt.getAllKeys()) { CompoundTag tag = nbt.getCompound(s); if (tag.contains(NBT_DIRECTION) && tag.contains(NBT_ITEM)) { Direction direction = Direction.from3DDataValue(tag.getInt(NBT_DIRECTION)); ItemStack item = ItemStack.of(tag.getCompound(NBT_ITEM)); int type = tag.contains(NBT_TYPE) ? tag.getInt(NBT_TYPE) : 0; if (type >= CoverType.values().length) { type = 0; } if (isValidCover(item)) { covers.put(direction, new Cover(item, CoverType.values()[type])); } } } } public CompoundTag writeToNbt() { CompoundTag list = new CompoundTag(); for (Map.Entry entry : covers.entrySet()) { CompoundTag tag = new CompoundTag(); tag.putInt(NBT_DIRECTION, entry.getKey().ordinal()); tag.put(NBT_ITEM, entry.getValue().getStack().save(new CompoundTag())); tag.putInt(NBT_TYPE, entry.getValue().getType().ordinal()); list.put(entry.getKey().ordinal() + "", tag); } return list; } public IItemHandlerModifiable getAsInventory() { ItemStackHandler handler = new ItemStackHandler(covers.size()); int i = 0; for (Map.Entry entry : covers.entrySet()) { ItemStack cover = entry.getValue().getType().createStack(); CoverItem.setItem(cover, entry.getValue().getStack()); handler.setStackInSlot(i++, cover); } return handler; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/cover/CoverType.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.cover; import com.refinedmods.refinedstorage.RSItems; import net.minecraft.world.item.ItemStack; public enum CoverType { NORMAL, HOLLOW; public ItemStack createStack() { return new ItemStack(this == NORMAL ? RSItems.COVER.get() : RSItems.HOLLOW_COVER.get()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/DiskDriveNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.*; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import com.refinedmods.refinedstorage.util.StackUtils; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.util.List; public class DiskDriveNetworkNode extends NetworkNode implements IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IType, IAccessType, IStorageDiskContainerContext { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "disk_drive"); private static final String NBT_PRIORITY = "Priority"; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_TYPE = "Type"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private static final int DISK_STATE_UPDATE_THROTTLE = 30; private static final Logger LOGGER = LogManager.getLogger(DiskDriveNetworkNode.class); private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final IStorageDisk[] itemDisks = new IStorageDisk[8]; private final IStorageDisk[] fluidDisks = new IStorageDisk[8]; private final BaseItemHandler disks = new BaseItemHandler(8) .addValidator(new StorageDiskItemValidator()) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!level.isClientSide) { StackUtils.createStorages( (ServerLevel) level, handler.getStackInSlot(slot), slot, itemDisks, fluidDisks, s -> new ItemDriveWrapperStorageDisk(DiskDriveNetworkNode.this, s), s -> new FluidDriveWrapperStorageDisk(DiskDriveNetworkNode.this, s) ); if (network != null) { network.getItemStorageCache().invalidate(InvalidateCause.DISK_INVENTORY_CHANGED); network.getFluidStorageCache().invalidate(InvalidateCause.DISK_INVENTORY_CHANGED); } if (!reading) { LevelUtils.updateBlock(level, pos); } } }); private int ticksSinceBlockUpdateRequested; private boolean blockUpdateRequested; private AccessType accessType = AccessType.INSERT_EXTRACT; private int priority = 0; private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private int type = IType.ITEMS; public DiskDriveNetworkNode(Level level, BlockPos pos) { super(level, pos); } public IStorageDisk[] getItemDisks() { return itemDisks; } public IStorageDisk[] getFluidDisks() { return fluidDisks; } @Override public int getEnergyUsage() { int usage = RS.SERVER_CONFIG.getDiskDrive().getUsage(); for (IStorage storage : itemDisks) { if (storage != null) { usage += RS.SERVER_CONFIG.getDiskDrive().getDiskUsage(); } } for (IStorage storage : fluidDisks) { if (storage != null) { usage += RS.SERVER_CONFIG.getDiskDrive().getDiskUsage(); } } return usage; } @Override public void update() { super.update(); if (blockUpdateRequested) { ++ticksSinceBlockUpdateRequested; if (ticksSinceBlockUpdateRequested > DISK_STATE_UPDATE_THROTTLE) { LevelUtils.updateBlock(level, pos); this.blockUpdateRequested = false; this.ticksSinceBlockUpdateRequested = 0; } } else { this.ticksSinceBlockUpdateRequested = 0; } } void requestBlockUpdate() { this.blockUpdateRequested = true; } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); LOGGER.debug("Connectivity state of disk drive at {} changed to {} due to {}", pos, state, cause); network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED)); network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED)); LevelUtils.updateBlock(level, pos); } @Override public void addItemStorages(List> storages) { for (IStorage storage : this.itemDisks) { if (storage != null) { storages.add(storage); } } } @Override public void addFluidStorages(List> storages) { for (IStorage storage : this.fluidDisks) { if (storage != null) { storages.add(storage); } } } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(disks, 0, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(disks, 0, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); StackUtils.writeItems(itemFilters, 1, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); tag.putInt(NBT_PRIORITY, priority); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_TYPE, type); AccessTypeUtils.writeAccessType(tag, accessType); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); StackUtils.readItems(itemFilters, 1, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } if (tag.contains(NBT_PRIORITY)) { priority = tag.getInt(NBT_PRIORITY); } if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } accessType = AccessTypeUtils.readAccessType(tag); } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } @Override public AccessType getAccessType() { return accessType; } @Override public void setAccessType(AccessType value) { this.accessType = value; if (network != null) { network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } markDirty(); } @Override public int getPriority() { return priority; } @Override public void setPriority(int priority) { this.priority = priority; markDirty(); if (network != null) { network.getItemStorageCache().sort(); network.getFluidStorageCache().sort(); } } public DiskState[] getDiskState() { DiskState[] diskStates = new DiskState[8]; for (int i = 0; i < 8; ++i) { DiskState state = DiskState.NONE; if (itemDisks[i] != null || fluidDisks[i] != null) { if (!canUpdate()) { state = DiskState.DISCONNECTED; } else { state = DiskState.get( itemDisks[i] != null ? itemDisks[i].getStored() : fluidDisks[i].getStored(), itemDisks[i] != null ? itemDisks[i].getCapacity() : fluidDisks[i].getCapacity() ); } } diskStates[i] = state; } return diskStates; } public IItemHandler getDisks() { return disks; } @Override public int getType() { return level.isClientSide ? DiskDriveBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; markDirty(); } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } @Override public IItemHandler getDrops() { return getDisks(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/FluidDriveWrapperStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class FluidDriveWrapperStorageDisk implements IStorageDisk { private final DiskDriveNetworkNode diskDrive; private final IStorageDisk parent; private DiskState lastState; public FluidDriveWrapperStorageDisk(DiskDriveNetworkNode diskDrive, IStorageDisk parent) { this.diskDrive = diskDrive; this.parent = parent; this.setSettings( () -> { DiskState currentState = DiskState.get(getStored(), getCapacity()); if (this.lastState != currentState) { this.lastState = currentState; diskDrive.requestBlockUpdate(); } }, diskDrive ); this.lastState = DiskState.get(getStored(), getCapacity()); } @Override public int getPriority() { return diskDrive.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { if (!IWhitelistBlacklist.acceptsFluid(diskDrive.getFluidFilters(), diskDrive.getWhitelistBlacklistMode(), diskDrive.getCompare(), stack)) { return StackUtils.copy(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskdrive/ItemDriveWrapperStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class ItemDriveWrapperStorageDisk implements IStorageDisk { private final DiskDriveNetworkNode diskDrive; private final IStorageDisk parent; private DiskState lastState; public ItemDriveWrapperStorageDisk(DiskDriveNetworkNode diskDrive, IStorageDisk parent) { this.diskDrive = diskDrive; this.parent = parent; this.setSettings( () -> { DiskState currentState = DiskState.get(getStored(), getCapacity()); if (this.lastState != currentState) { this.lastState = currentState; diskDrive.requestBlockUpdate(); } }, diskDrive ); this.lastState = DiskState.get(getStored(), getCapacity()); } @Override public int getPriority() { return diskDrive.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { if (!IWhitelistBlacklist.acceptsItem(diskDrive.getItemFilters(), diskDrive.getWhitelistBlacklistMode(), diskDrive.getCompare(), stack)) { return ItemHandlerHelper.copyStackWithSize(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/DiskManipulatorNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.ProxyItemHandler; import com.refinedmods.refinedstorage.inventory.item.UpgradeItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.util.StackUtils; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.wrapper.CombinedInvWrapper; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; public class DiskManipulatorNetworkNode extends NetworkNode implements IComparable, IWhitelistBlacklist, IType, IStorageDiskContainerContext { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "disk_manipulator"); public static final int IO_MODE_INSERT = 0; public static final int IO_MODE_EXTRACT = 1; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_TYPE = "Type"; private static final String NBT_IO_MODE = "IOMode"; private static final String NBT_FLUID_FILTERS = "FluidFilters"; private final IStorageDisk[] itemDisks = new IStorageDisk[6]; private final IStorageDisk[] fluidDisks = new IStorageDisk[6]; private final BaseItemHandler inputDisks = new BaseItemHandler(3) .addValidator(new StorageDiskItemValidator()) .addListener(new NetworkNodeInventoryListener(this)) .addListener((handler, slot, reading) -> { if (!level.isClientSide) { StackUtils.createStorages( (ServerLevel) level, handler.getStackInSlot(slot), slot, itemDisks, fluidDisks, s -> new StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode.this, s), s -> new StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode.this, s) ); if (!reading) { LevelUtils.updateBlock(level, pos); } } }); private final BaseItemHandler outputDisks = new BaseItemHandler(3) .addValidator(new StorageDiskItemValidator()) .addListener(new NetworkNodeInventoryListener(this)) .addListener(((handler, slot, reading) -> { if (!level.isClientSide) { StackUtils.createStorages( (ServerLevel) level, handler.getStackInSlot(slot), 3 + slot, itemDisks, fluidDisks, s -> new StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode.this, s), s -> new StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode.this, s) ); if (!reading) { LevelUtils.updateBlock(level, pos); } } })); private final ProxyItemHandler disks = new ProxyItemHandler(inputDisks, outputDisks); private final BaseItemHandler itemFilters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final FluidInventory fluidFilters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private int type = IType.ITEMS; private final UpgradeItemHandler upgrades = (UpgradeItemHandler) new UpgradeItemHandler(4, UpgradeItem.Type.SPEED, UpgradeItem.Type.STACK) { @Override public int getStackInteractCount() { int count = super.getStackInteractCount(); if (type == IType.FLUIDS) { count *= FluidType.BUCKET_VOLUME; } return count; } }.addListener(new NetworkNodeInventoryListener(this)); private int ioMode = IO_MODE_INSERT; public DiskManipulatorNetworkNode(Level level, BlockPos pos) { super(level, pos); } @Override public int getEnergyUsage() { return RS.SERVER_CONFIG.getDiskManipulator().getUsage() + upgrades.getEnergyUsage(); } @Override public void update() { super.update(); if (!canUpdate() || ticks % upgrades.getSpeed() != 0) { return; } int slot = 0; if (type == IType.ITEMS) { while (slot < 3 && (itemDisks[slot] == null || isItemDiskDone(itemDisks[slot], slot))) { slot++; } if (slot == 3) { return; } IStorageDisk storage = itemDisks[slot]; if (ioMode == IO_MODE_INSERT) { insertItemIntoNetwork(storage); } else if (ioMode == IO_MODE_EXTRACT) { extractItemFromNetwork(storage, slot); } } else if (type == IType.FLUIDS) { while (slot < 3 && (fluidDisks[slot] == null || isFluidDiskDone(fluidDisks[slot], slot))) { slot++; } if (slot == 3) { return; } IStorageDisk storage = fluidDisks[slot]; if (ioMode == IO_MODE_INSERT) { insertFluidIntoNetwork(storage, slot); } else if (ioMode == IO_MODE_EXTRACT) { extractFluidFromNetwork(storage, slot); } } } private void insertItemIntoNetwork(IStorageDisk storage) { List stacks = new ArrayList<>(storage.getStacks()); for (int i = 0; i < stacks.size(); ++i) { ItemStack stack = stacks.get(i); ItemStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.PERFORM); if (extracted.isEmpty()) { continue; } ItemStack remainder = network.insertItem(extracted, extracted.getCount(), Action.PERFORM); if (remainder.isEmpty()) { break; } // We need to check if the stack was inserted storage.insert(((extracted == remainder) ? remainder.copy() : remainder), remainder.getCount(), Action.PERFORM); } } // Iterate through disk stacks, if none can be inserted, return that it is done processing and can be output. private boolean isItemDiskDone(IStorageDisk storage, int slot) { if (ioMode == IO_MODE_INSERT && storage.getStored() == 0) { moveDriveToOutput(slot); return true; } // In Extract mode, we just need to check if the disk is full or not. if (ioMode == IO_MODE_EXTRACT) { if (storage.getStored() == storage.getCapacity()) { moveDriveToOutput(slot); return true; } else { return false; } } List stacks = new ArrayList<>(storage.getStacks()); for (int i = 0; i < stacks.size(); ++i) { ItemStack stack = stacks.get(i); ItemStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.SIMULATE); if (extracted.isEmpty()) { continue; } ItemStack remainder = network.insertItem(extracted, extracted.getCount(), Action.SIMULATE); if (remainder.isEmpty()) { // An item could be inserted (no remainders when trying to). This disk isn't done. return false; } } return true; } private void extractItemFromNetwork(IStorageDisk storage, int slot) { ItemStack extracted = ItemStack.EMPTY; int i = 0; if (itemFilters.isEmpty()) { ItemStack toExtract = null; List networkItems = network.getItemStorageCache().getList().getStacks().stream().map(StackListEntry::getStack).collect(Collectors.toList()); int j = 0; while ((toExtract == null || toExtract.isEmpty()) && j < networkItems.size()) { toExtract = networkItems.get(j++); } if (toExtract != null) { extracted = network.extractItem(toExtract, upgrades.getStackInteractCount(), compare, Action.PERFORM); } } else { while (itemFilters.getSlots() > i && extracted.isEmpty()) { ItemStack filterStack = ItemStack.EMPTY; while (itemFilters.getSlots() > i && filterStack.isEmpty()) { filterStack = itemFilters.getStackInSlot(i++); } if (!filterStack.isEmpty()) { extracted = network.extractItem(filterStack, upgrades.getStackInteractCount(), compare, Action.PERFORM); } } } if (extracted.isEmpty()) { moveDriveToOutput(slot); return; } ItemStack remainder = storage.insert(extracted, extracted.getCount(), Action.PERFORM); network.insertItem(remainder, remainder.getCount(), Action.PERFORM); } private void insertFluidIntoNetwork(IStorageDisk storage, int slot) { List stacks = new ArrayList<>(storage.getStacks()); FluidStack extracted = FluidStack.EMPTY; int i = 0; while (extracted.isEmpty() && stacks.size() > i) { FluidStack stack = stacks.get(i++); extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.PERFORM); } if (extracted.isEmpty()) { moveDriveToOutput(slot); return; } FluidStack remainder = network.insertFluid(extracted, extracted.getAmount(), Action.PERFORM); storage.insert(remainder, remainder.getAmount(), Action.PERFORM); } private boolean isFluidDiskDone(IStorageDisk storage, int slot) { if (ioMode == IO_MODE_INSERT && storage.getStored() == 0) { moveDriveToOutput(slot); return true; } //In Extract mode, we just need to check if the disk is full or not. if (ioMode == IO_MODE_EXTRACT) { if (storage.getStored() == storage.getCapacity()) { moveDriveToOutput(slot); return true; } else { return false; } } List stacks = new ArrayList<>(storage.getStacks()); for (int i = 0; i < stacks.size(); ++i) { FluidStack stack = stacks.get(i); FluidStack extracted = storage.extract(stack, upgrades.getStackInteractCount(), compare, Action.SIMULATE); if (extracted.isEmpty()) { continue; } FluidStack remainder = network.insertFluid(extracted, extracted.getAmount(), Action.SIMULATE); if (remainder.isEmpty()) { // A fluid could be inserted (no remainders when trying to). This disk isn't done. return false; } } return true; } private void extractFluidFromNetwork(IStorageDisk storage, int slot) { FluidStack extracted = FluidStack.EMPTY; int i = 0; if (fluidFilters.isEmpty()) { FluidStack toExtract = null; List networkFluids = network.getFluidStorageCache().getList().getStacks().stream().map(StackListEntry::getStack).collect(Collectors.toList()); int j = 0; while ((toExtract == null || toExtract.getAmount() == 0) && j < networkFluids.size()) { toExtract = networkFluids.get(j++); } if (toExtract != null) { extracted = network.extractFluid(toExtract, upgrades.getStackInteractCount(), compare, Action.PERFORM); } } else { while (fluidFilters.getSlots() > i && extracted.isEmpty()) { FluidStack filterStack = FluidStack.EMPTY; while (fluidFilters.getSlots() > i && filterStack.isEmpty()) { filterStack = fluidFilters.getFluid(i++); } if (!filterStack.isEmpty()) { extracted = network.extractFluid(filterStack, upgrades.getStackInteractCount(), compare, Action.PERFORM); } } } if (extracted.isEmpty()) { moveDriveToOutput(slot); return; } FluidStack remainder = storage.insert(extracted, extracted.getAmount(), Action.PERFORM); network.insertFluid(remainder, remainder.getAmount(), Action.PERFORM); } private void moveDriveToOutput(int slot) { ItemStack disk = inputDisks.getStackInSlot(slot); if (!disk.isEmpty()) { int i = 0; while (i < 3 && !outputDisks.getStackInSlot(i).isEmpty()) { i++; } if (i == 3) { return; } inputDisks.extractItem(slot, 1, false); outputDisks.insertItem(i, disk, false); } } public DiskState[] getDiskState() { DiskState[] diskStates = new DiskState[6]; for (int i = 0; i < 6; ++i) { DiskState state = DiskState.NONE; if (itemDisks[i] != null || fluidDisks[i] != null) { if (!canUpdate()) { state = DiskState.DISCONNECTED; } else { state = DiskState.get( itemDisks[i] != null ? itemDisks[i].getStored() : fluidDisks[i].getStored(), itemDisks[i] != null ? itemDisks[i].getCapacity() : fluidDisks[i].getCapacity() ); } } diskStates[i] = state; } return diskStates; } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; } @Override public int getType() { return level.isClientSide ? DiskManipulatorBlockEntity.TYPE.getValue() : type; } @Override public void setType(int type) { this.type = type; } @Override public IItemHandlerModifiable getItemFilters() { return itemFilters; } @Override public FluidInventory getFluidFilters() { return fluidFilters; } @Override public int getWhitelistBlacklistMode() { return this.mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; } public int getIoMode() { return ioMode; } public void setIoMode(int ioMode) { this.ioMode = ioMode; } public IItemHandler getInputDisks() { return inputDisks; } public IItemHandler getOutputDisks() { return outputDisks; } public ProxyItemHandler getDisks() { return disks; } public IItemHandler getUpgrades() { return upgrades; } @Override public void read(CompoundTag tag) { super.read(tag); StackUtils.readItems(upgrades, 3, tag); StackUtils.readItems(inputDisks, 4, tag); StackUtils.readItems(outputDisks, 5, tag); } @Override public ResourceLocation getId() { return ID; } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); StackUtils.writeItems(upgrades, 3, tag); StackUtils.writeItems(inputDisks, 4, tag); StackUtils.writeItems(outputDisks, 5, tag); return tag; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); StackUtils.writeItems(itemFilters, 1, tag); tag.put(NBT_FLUID_FILTERS, fluidFilters.writeToNbt()); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); tag.putInt(NBT_TYPE, type); tag.putInt(NBT_IO_MODE, ioMode); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); StackUtils.readItems(itemFilters, 1, tag); if (tag.contains(NBT_FLUID_FILTERS)) { fluidFilters.readFromNbt(tag.getCompound(NBT_FLUID_FILTERS)); } if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } if (tag.contains(NBT_TYPE)) { type = tag.getInt(NBT_TYPE); } if (tag.contains(NBT_IO_MODE)) { ioMode = tag.getInt(NBT_IO_MODE); } } @Override public IItemHandler getDrops() { return new CombinedInvWrapper(inputDisks, outputDisks, upgrades); } @Override public AccessType getAccessType() { return AccessType.INSERT_EXTRACT; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/StorageDiskFluidManipulatorWrapper.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.util.StackUtils; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class StorageDiskFluidManipulatorWrapper implements IStorageDisk { private final DiskManipulatorNetworkNode diskManipulator; private final IStorageDisk parent; private DiskState lastState; public StorageDiskFluidManipulatorWrapper(DiskManipulatorNetworkNode diskManipulator, IStorageDisk parent) { this.diskManipulator = diskManipulator; this.parent = parent; this.setSettings( () -> { DiskState currentState = DiskState.get(getStored(), getCapacity()); if (lastState != currentState) { lastState = currentState; LevelUtils.updateBlock(diskManipulator.getLevel(), diskManipulator.getPos()); } }, diskManipulator ); this.lastState = DiskState.get(getStored(), getCapacity()); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } if (!IWhitelistBlacklist.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) { return StackUtils.copy(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { if (!IWhitelistBlacklist.acceptsFluid(diskManipulator.getFluidFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) { return FluidStack.EMPTY; } return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getPriority() { return parent.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/diskmanipulator/StorageDiskItemManipulatorWrapper.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class StorageDiskItemManipulatorWrapper implements IStorageDisk { private final DiskManipulatorNetworkNode diskManipulator; private final IStorageDisk parent; private DiskState lastState; public StorageDiskItemManipulatorWrapper(DiskManipulatorNetworkNode diskManipulator, IStorageDisk parent) { this.diskManipulator = diskManipulator; this.parent = parent; this.setSettings( () -> { DiskState currentState = DiskState.get(getStored(), getCapacity()); if (lastState != currentState) { lastState = currentState; LevelUtils.updateBlock(diskManipulator.getLevel(), diskManipulator.getPos()); } }, diskManipulator ); this.lastState = DiskState.get(getStored(), getCapacity()); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } if (!IWhitelistBlacklist.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) { return ItemHandlerHelper.copyStackWithSize(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { if (!IWhitelistBlacklist.acceptsItem(diskManipulator.getItemFilters(), diskManipulator.getWhitelistBlacklistMode(), diskManipulator.getCompare(), stack)) { return ItemStack.EMPTY; } return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getPriority() { return parent.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.storage; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause; import com.refinedmods.refinedstorage.apiimpl.network.node.IStorageScreen; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.cache.FluidStorageCache; import com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IAccessType; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IPrioritizable; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeFluidInventoryListener; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class FluidStorageNetworkNode extends NetworkNode implements IStorageScreen, IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IAccessType, IStorageDiskContainerContext { public static final ResourceLocation SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "64k_fluid_storage_block"); public static final ResourceLocation TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "256k_fluid_storage_block"); public static final ResourceLocation THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "1024k_fluid_storage_block"); public static final ResourceLocation FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "4096k_fluid_storage_block"); public static final ResourceLocation CREATIVE_FLUID_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "creative_fluid_storage_block"); public static final String NBT_ID = "Id"; private static final Logger LOGGER = LogManager.getLogger(FluidStorageNetworkNode.class); private static final String NBT_PRIORITY = "Priority"; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_FILTERS = "Filters"; private final FluidInventory filters = new FluidInventory(9).addListener(new NetworkNodeFluidInventoryListener(this)); private final FluidStorageType type; private AccessType accessType = AccessType.INSERT_EXTRACT; private int priority = 0; private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private UUID storageId = UUID.randomUUID(); private IStorageDisk storage; public FluidStorageNetworkNode(Level level, BlockPos pos, FluidStorageType type) { super(level, pos); this.type = type; } public static ResourceLocation getId(FluidStorageType type) { switch (type) { case SIXTY_FOUR_K: return SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID; case TWO_HUNDRED_FIFTY_SIX_K: return TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID; case THOUSAND_TWENTY_FOUR_K: return THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID; case FOUR_THOUSAND_NINETY_SIX_K: return FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID; case CREATIVE: return CREATIVE_FLUID_STORAGE_BLOCK_ID; default: throw new IllegalArgumentException("Unknown storage type " + type); } } @Override public int getEnergyUsage() { switch (type) { case SIXTY_FOUR_K: return RS.SERVER_CONFIG.getFluidStorageBlock().getSixtyFourKUsage(); case TWO_HUNDRED_FIFTY_SIX_K: return RS.SERVER_CONFIG.getFluidStorageBlock().getTwoHundredFiftySixKUsage(); case THOUSAND_TWENTY_FOUR_K: return RS.SERVER_CONFIG.getFluidStorageBlock().getThousandTwentyFourKUsage(); case FOUR_THOUSAND_NINETY_SIX_K: return RS.SERVER_CONFIG.getFluidStorageBlock().getFourThousandNinetySixKUsage(); case CREATIVE: return RS.SERVER_CONFIG.getFluidStorageBlock().getCreativeUsage(); default: return 0; } } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); LOGGER.debug("Connectivity state of fluid storage block at {} changed to {} due to {}", pos, state, cause); network.getNodeGraph().runActionWhenPossible(FluidStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED)); } @Override public void addItemStorages(List> storages) { // NO OP } @Override public void addFluidStorages(List> storages) { if (storage == null) { loadStorage(null); } storages.add(storage); } @Override public ResourceLocation getId() { return getId(type); } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.putUUID(NBT_ID, storageId); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.hasUUID(NBT_ID)) { storageId = tag.getUUID(NBT_ID); loadStorage(null); } } public void loadStorage(@Nullable Player owner) { IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).get(storageId); if (disk == null) { disk = API.instance().createDefaultFluidDisk((ServerLevel) level, type.getCapacity(), owner); API.instance().getStorageDiskManager((ServerLevel) level).set(storageId, disk); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); } this.storage = new FluidStorageWrapperStorageDisk(this, disk); } public UUID getStorageId() { return storageId; } public void setStorageId(UUID id) { this.storageId = id; markDirty(); } public IStorageDisk getStorage() { return storage; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); tag.put(NBT_FILTERS, filters.writeToNbt()); tag.putInt(NBT_PRIORITY, priority); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); AccessTypeUtils.writeAccessType(tag, accessType); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); if (tag.contains(NBT_FILTERS)) { filters.readFromNbt(tag.getCompound(NBT_FILTERS)); } if (tag.contains(NBT_PRIORITY)) { priority = tag.getInt(NBT_PRIORITY); } if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } accessType = AccessTypeUtils.readAccessType(tag); } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } public FluidInventory getFilters() { return filters; } @Override public Component getTitle() { return Component.translatable("block.refinedstorage." + type.getName() + "_fluid_storage_block"); } @Override public long getStored() { return FluidStorageBlockEntity.STORED.getValue(); } @Override public long getCapacity() { return type.getCapacity(); } @Override public AccessType getAccessType() { return accessType; } @Override public void setAccessType(AccessType value) { this.accessType = value; if (network != null) { network.getFluidStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } markDirty(); } @Override public int getPriority() { return priority; } @Override public void setPriority(int priority) { this.priority = priority; markDirty(); if (network != null) { network.getFluidStorageCache().sort(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/FluidStorageWrapperStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.storage; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class FluidStorageWrapperStorageDisk implements IStorageDisk { private final FluidStorageNetworkNode storage; private final IStorageDisk parent; public FluidStorageWrapperStorageDisk(FluidStorageNetworkNode storage, IStorageDisk parent) { this.storage = storage; this.parent = parent; this.setSettings(null, storage); } @Override public int getPriority() { return storage.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { if (!IWhitelistBlacklist.acceptsFluid(storage.getFilters(), storage.getWhitelistBlacklistMode(), storage.getCompare(), stack)) { return StackUtils.copy(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/ItemStorageWrapperStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.storage; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class ItemStorageWrapperStorageDisk implements IStorageDisk { private final StorageNetworkNode storage; private final IStorageDisk parent; public ItemStorageWrapperStorageDisk(StorageNetworkNode storage, IStorageDisk parent) { this.storage = storage; this.parent = parent; this.setSettings(null, storage); } @Override public int getPriority() { return storage.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { if (!IWhitelistBlacklist.acceptsItem(storage.getFilters(), storage.getWhitelistBlacklistMode(), storage.getCompare(), stack)) { return ItemHandlerHelper.copyStackWithSize(stack, size); } return parent.insert(stack, size, action); } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { return parent.extract(stack, size, flags, action); } @Override public int getStored() { return parent.getStored(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/node/storage/StorageNetworkNode.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.node.storage; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.ConnectivityStateChangeCause; import com.refinedmods.refinedstorage.apiimpl.network.node.IStorageScreen; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.cache.ItemStorageCache; import com.refinedmods.refinedstorage.blockentity.StorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IAccessType; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IPrioritizable; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.listener.NetworkNodeInventoryListener; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class StorageNetworkNode extends NetworkNode implements IStorageScreen, IStorageProvider, IComparable, IWhitelistBlacklist, IPrioritizable, IAccessType, IStorageDiskContainerContext { public static final ResourceLocation ONE_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "1k_storage_block"); public static final ResourceLocation FOUR_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "4k_storage_block"); public static final ResourceLocation SIXTEEN_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "16k_storage_block"); public static final ResourceLocation SIXTY_FOUR_K_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "64k_storage_block"); public static final ResourceLocation CREATIVE_STORAGE_BLOCK_ID = new ResourceLocation(RS.ID, "creative_storage_block"); public static final String NBT_ID = "Id"; private static final Logger LOGGER = LogManager.getLogger(StorageNetworkNode.class); private static final String NBT_PRIORITY = "Priority"; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private final BaseItemHandler filters = new BaseItemHandler(9).addListener(new NetworkNodeInventoryListener(this)); private final ItemStorageType type; private AccessType accessType = AccessType.INSERT_EXTRACT; private int priority = 0; private int compare = IComparer.COMPARE_NBT; private int mode = IWhitelistBlacklist.BLACKLIST; private UUID storageId = UUID.randomUUID(); private IStorageDisk storage; public StorageNetworkNode(Level level, BlockPos pos, ItemStorageType type) { super(level, pos); this.type = type; } public static ResourceLocation getId(ItemStorageType type) { switch (type) { case ONE_K: return ONE_K_STORAGE_BLOCK_ID; case FOUR_K: return FOUR_K_STORAGE_BLOCK_ID; case SIXTEEN_K: return SIXTEEN_K_STORAGE_BLOCK_ID; case SIXTY_FOUR_K: return SIXTY_FOUR_K_STORAGE_BLOCK_ID; case CREATIVE: return CREATIVE_STORAGE_BLOCK_ID; default: throw new IllegalArgumentException("Unknown storage type " + type); } } @Override public int getEnergyUsage() { switch (type) { case ONE_K: return RS.SERVER_CONFIG.getStorageBlock().getOneKUsage(); case FOUR_K: return RS.SERVER_CONFIG.getStorageBlock().getFourKUsage(); case SIXTEEN_K: return RS.SERVER_CONFIG.getStorageBlock().getSixteenKUsage(); case SIXTY_FOUR_K: return RS.SERVER_CONFIG.getStorageBlock().getSixtyFourKUsage(); case CREATIVE: return RS.SERVER_CONFIG.getStorageBlock().getCreativeUsage(); default: return 0; } } @Override public void onConnectedStateChange(INetwork network, boolean state, ConnectivityStateChangeCause cause) { super.onConnectedStateChange(network, state, cause); LOGGER.debug("Connectivity state of item storage block at {} changed to {} due to {}", pos, state, cause); network.getNodeGraph().runActionWhenPossible(ItemStorageCache.INVALIDATE_ACTION.apply(InvalidateCause.CONNECTED_STATE_CHANGED)); } @Override public void addItemStorages(List> storages) { if (storage == null) { loadStorage(null); } storages.add(storage); } @Override public void addFluidStorages(List> storages) { // NO OP } @Override public ResourceLocation getId() { return getId(type); } @Override public CompoundTag write(CompoundTag tag) { super.write(tag); tag.putUUID(NBT_ID, storageId); return tag; } @Override public void read(CompoundTag tag) { super.read(tag); if (tag.hasUUID(NBT_ID)) { storageId = tag.getUUID(NBT_ID); loadStorage(null); } } public void loadStorage(@Nullable Player owner) { IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).get(storageId); if (disk == null) { disk = API.instance().createDefaultItemDisk((ServerLevel) level, type.getCapacity(), owner); API.instance().getStorageDiskManager((ServerLevel) level).set(storageId, disk); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); } this.storage = new ItemStorageWrapperStorageDisk(this, disk); } public UUID getStorageId() { return storageId; } public void setStorageId(UUID id) { this.storageId = id; markDirty(); } public IStorageDisk getStorage() { return storage; } @Override public CompoundTag writeConfiguration(CompoundTag tag) { super.writeConfiguration(tag); StackUtils.writeItems(filters, 0, tag); tag.putInt(NBT_PRIORITY, priority); tag.putInt(NBT_COMPARE, compare); tag.putInt(NBT_MODE, mode); AccessTypeUtils.writeAccessType(tag, accessType); return tag; } @Override public void readConfiguration(CompoundTag tag) { super.readConfiguration(tag); StackUtils.readItems(filters, 0, tag); if (tag.contains(NBT_PRIORITY)) { priority = tag.getInt(NBT_PRIORITY); } if (tag.contains(NBT_COMPARE)) { compare = tag.getInt(NBT_COMPARE); } if (tag.contains(NBT_MODE)) { mode = tag.getInt(NBT_MODE); } accessType = AccessTypeUtils.readAccessType(tag); } @Override public int getCompare() { return compare; } @Override public void setCompare(int compare) { this.compare = compare; markDirty(); } @Override public int getWhitelistBlacklistMode() { return mode; } @Override public void setWhitelistBlacklistMode(int mode) { this.mode = mode; markDirty(); } public BaseItemHandler getFilters() { return filters; } @Override public Component getTitle() { return Component.translatable("block.refinedstorage." + type.getName() + "_storage_block"); } @Override public long getStored() { return StorageBlockEntity.STORED.getValue(); } @Override public long getCapacity() { return type.getCapacity(); } @Override public AccessType getAccessType() { return accessType; } @Override public void setAccessType(AccessType value) { this.accessType = value; if (network != null) { network.getItemStorageCache().invalidate(InvalidateCause.DEVICE_CONFIGURATION_CHANGED); } markDirty(); } @Override public int getPriority() { return priority; } @Override public void setPriority(int priority) { this.priority = priority; markDirty(); if (network != null) { network.getItemStorageCache().sort(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/security/SecurityCard.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.security; import com.refinedmods.refinedstorage.api.network.security.ISecurityCard; import com.refinedmods.refinedstorage.api.network.security.Permission; import javax.annotation.Nullable; import java.util.EnumMap; import java.util.Map; import java.util.UUID; public class SecurityCard implements ISecurityCard { private final UUID owner; private final Map permissions = new EnumMap<>(Permission.class); public SecurityCard(@Nullable UUID owner) { this.owner = owner; } public Map getPermissions() { return permissions; } @Override @Nullable public UUID getOwner() { return owner; } @Override public boolean hasPermission(Permission permission) { return permissions.get(permission); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/network/security/SecurityManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.network.security; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.network.security.ISecurityCard; import com.refinedmods.refinedstorage.api.network.security.ISecurityCardContainer; import com.refinedmods.refinedstorage.api.network.security.ISecurityManager; import com.refinedmods.refinedstorage.api.network.security.Permission; import net.minecraft.server.players.ServerOpList; import net.minecraft.world.entity.player.Player; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class SecurityManager implements ISecurityManager { private final INetwork network; private final Map cards = new HashMap<>(); private ISecurityCard globalCard; public SecurityManager(INetwork network) { this.network = network; } @Override public boolean hasPermission(Permission permission, Player player) { ServerOpList ops = player.getServer().getPlayerList().getOps(); if (ops.get(player.getGameProfile()) != null) { return true; } UUID uuid = player.getGameProfile().getId(); if (!cards.containsKey(uuid)) { if (globalCard != null) { return globalCard.hasPermission(permission); } return true; } return cards.get(uuid).hasPermission(permission); } @Override public void invalidate() { this.cards.clear(); this.globalCard = null; for (INetworkNodeGraphEntry entry : network.getNodeGraph().all()) { if (entry.getNode() instanceof ISecurityCardContainer && entry.getNode().isActive()) { ISecurityCardContainer container = (ISecurityCardContainer) entry.getNode(); for (ISecurityCard card : container.getCards()) { if (card.getOwner() == null) { throw new IllegalStateException("Owner in #getCards() cannot be null!"); } this.cards.put(card.getOwner(), card); } if (container.getGlobalCard() != null) { this.globalCard = container.getGlobalCard(); } } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/render/CraftingMonitorElementDrawers.java ================================================ package com.refinedmods.refinedstorage.apiimpl.render; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.resources.ResourceLocation; public class CraftingMonitorElementDrawers extends ElementDrawers { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafting_preview.png"); private final IElementDrawer overlayDrawer; private final IElementDrawer errorDrawer; public CraftingMonitorElementDrawers(BaseScreen screen, int itemWidth, int itemHeight) { super(screen); this.overlayDrawer = (graphics, x, y, color) -> { RenderSystem.setShaderColor(1, 1, 1, 1); graphics.fill(x, y, x + itemWidth, y + itemHeight, color); }; this.errorDrawer = (graphics, x, y, nothing) -> { RenderSystem.setShaderColor(1, 1, 1, 1); graphics.blit(TEXTURE, x + itemWidth - 12 - 2, y + itemHeight - 12 - 2, 0, 244, 12, 12); }; } @Override public IElementDrawer getOverlayDrawer() { return overlayDrawer; } @Override public IElementDrawer getErrorDrawer() { return errorDrawer; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/render/CraftingPreviewElementDrawers.java ================================================ package com.refinedmods.refinedstorage.apiimpl.render; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.screen.grid.CraftingPreviewScreen; import net.minecraft.world.inventory.AbstractContainerMenu; public class CraftingPreviewElementDrawers extends ElementDrawers { private final IElementDrawer overlayDrawer = (graphics, x, y, color) -> { RenderSystem.setShaderColor(1, 1, 1, 1); graphics.fill(x, y, x + 73, y + 29, color); }; public CraftingPreviewElementDrawers(CraftingPreviewScreen screen) { super(screen); } @Override public IElementDrawer getOverlayDrawer() { return overlayDrawer; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/render/ElementDrawers.java ================================================ package com.refinedmods.refinedstorage.apiimpl.render; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.render.FluidRenderer; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class ElementDrawers implements IElementDrawers { protected final BaseScreen screen; public ElementDrawers(BaseScreen screen) { this.screen = screen; } @Override public IElementDrawer getItemDrawer() { return screen::renderItem; } @Override public IElementDrawer getFluidDrawer() { return FluidRenderer.INSTANCE::render; } @Override public IElementDrawer getStringDrawer() { return screen::renderString; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/FluidStorageType.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage; public enum FluidStorageType { SIXTY_FOUR_K("64k", 64_000), TWO_HUNDRED_FIFTY_SIX_K("256k", 256_000), THOUSAND_TWENTY_FOUR_K("1024k", 1024_000), FOUR_THOUSAND_NINETY_SIX_K("4096k", 4096_000), CREATIVE("creative", -1); private final String name; private final int capacity; FluidStorageType(String name, int capacity) { this.name = name; this.capacity = capacity; } public String getName() { return name; } public int getCapacity() { return capacity; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/ItemStorageType.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage; public enum ItemStorageType { ONE_K("1k", 1000), FOUR_K("4k", 4000), SIXTEEN_K("16k", 16_000), SIXTY_FOUR_K("64k", 64_000), CREATIVE("creative", -1); private final String name; private final int capacity; ItemStorageType(String name, int capacity) { this.name = name; this.capacity = capacity; } public String getName() { return name; } public int getCapacity() { return capacity; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/FluidStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.world.item.ItemStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.function.Function; public class FluidStorageCache implements IStorageCache { public static final Function> INVALIDATE_ACTION = cause -> invalidatedNetwork -> invalidatedNetwork.getFluidStorageCache().invalidate(cause); private static final Logger LOGGER = LogManager.getLogger(FluidStorageCache.class); private final INetwork network; private final CopyOnWriteArrayList> storages = new CopyOnWriteArrayList<>(); private final IStackList list = API.instance().createFluidStackList(); private final IStackList craftables = API.instance().createFluidStackList(); private final List> listeners = new LinkedList<>(); private final List> batchedChanges = new ArrayList<>(); public FluidStorageCache(INetwork network) { this.network = network; } @Override public void invalidate(InvalidateCause cause) { LOGGER.debug("Invalidating fluid storage cache of network at position {} due to {}", network.getPosition(), cause); storages.clear(); network.getNodeGraph() .all() .stream() .map(INetworkNodeGraphEntry::getNode) .filter(node -> node.isActive() && node instanceof IStorageProvider) .forEach(node -> ((IStorageProvider) node).addFluidStorages(storages)); list.clear(); sort(); for (IStorage storage : storages) { if (storage.getAccessType() == AccessType.INSERT) { continue; } for (FluidStack stack : storage.getStacks()) { if (!stack.isEmpty()) { add(stack, stack.getAmount(), true, false); } } } listeners.forEach(IStorageCacheListener::onInvalidated); } @Override public void add(@Nonnull FluidStack stack, int size, boolean rebuilding, boolean batched) { StackListResult result = list.add(stack, size); if (!rebuilding) { if (!batched) { listeners.forEach(l -> l.onChanged(result)); } else { batchedChanges.add(result); } } } @Override public void remove(@Nonnull FluidStack stack, int size, boolean batched) { StackListResult result = list.remove(stack, size); if (result != null) { if (!batched) { listeners.forEach(l -> l.onChanged(result)); } else { batchedChanges.add(result); } } } @Override public void flush() { if (!batchedChanges.isEmpty()) { if (batchedChanges.size() > 1) { listeners.forEach(l -> l.onChangedBulk(batchedChanges)); } else { batchedChanges.forEach(change -> listeners.forEach(l -> l.onChanged(change))); } batchedChanges.clear(); } } @Override public void addListener(IStorageCacheListener listener) { listeners.add(listener); listener.onAttached(); } @Override public void removeListener(IStorageCacheListener listener) { listeners.remove(listener); } @Override public void reAttachListeners() { listeners.forEach(IStorageCacheListener::onAttached); } @Override public void sort() { storages.sort(IStorage.COMPARATOR); } @Override public IStackList getList() { return list; } @Override public IStackList getCraftablesList() { return craftables; } @Override public List getGridStacks() { final List stacks = new ArrayList<>(); for (StackListEntry stack : network.getFluidStorageCache().getList().getStacks()) { stacks.add(FluidGridStack.of( stack, network.getFluidStorageTracker(), network.getFluidStorageCache().getCraftablesList(), false )); } for (StackListEntry stack : network.getFluidStorageCache().getCraftablesList().getStacks()) { stacks.add(FluidGridStack.of( stack, network.getFluidStorageTracker(), network.getFluidStorageCache().getList(), true )); } return stacks; } @Override public List> getStorages() { return storages; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/ItemStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.world.item.ItemStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; import java.util.function.Function; public class ItemStorageCache implements IStorageCache { public static final Function> INVALIDATE_ACTION = cause -> invalidatedNetwork -> invalidatedNetwork.getItemStorageCache().invalidate(cause); private static final Logger LOGGER = LogManager.getLogger(ItemStorageCache.class); private final INetwork network; private final CopyOnWriteArrayList> storages = new CopyOnWriteArrayList<>(); private final IStackList list = API.instance().createItemStackList(); private final IStackList craftables = API.instance().createItemStackList(); private final List> listeners = new LinkedList<>(); private final List> batchedChanges = new ArrayList<>(); public ItemStorageCache(INetwork network) { this.network = network; } @Override public void invalidate(InvalidateCause cause) { LOGGER.debug("Invalidating item storage cache of network at position {} due to {}", network.getPosition(), cause); storages.clear(); network.getNodeGraph() .all() .stream() .map(INetworkNodeGraphEntry::getNode) .filter(node -> node.isActive() && node instanceof IStorageProvider) .forEach(node -> ((IStorageProvider) node).addItemStorages(storages)); list.clear(); sort(); for (IStorage storage : storages) { if (storage.getAccessType() == AccessType.INSERT) { continue; } for (ItemStack stack : storage.getStacks()) { if (!stack.isEmpty()) { add(stack, stack.getCount(), true, false); } } } listeners.forEach(IStorageCacheListener::onInvalidated); } @Override public void add(@Nonnull ItemStack stack, int size, boolean rebuilding, boolean batched) { StackListResult result = list.add(stack, size); if (!rebuilding) { if (!batched) { listeners.forEach(l -> l.onChanged(result)); } else { batchedChanges.add(result); } } } @Override public void remove(@Nonnull ItemStack stack, int size, boolean batched) { StackListResult result = list.remove(stack, size); if (result != null) { if (!batched) { listeners.forEach(l -> l.onChanged(result)); } else { batchedChanges.add(result); } } } @Override public void flush() { if (!batchedChanges.isEmpty()) { if (batchedChanges.size() > 1) { listeners.forEach(l -> l.onChangedBulk(batchedChanges)); } else { batchedChanges.forEach(change -> listeners.forEach(l -> l.onChanged(change))); } batchedChanges.clear(); } } @Override public void addListener(IStorageCacheListener listener) { listeners.add(listener); listener.onAttached(); } @Override public void removeListener(IStorageCacheListener listener) { listeners.remove(listener); } @Override public void reAttachListeners() { listeners.forEach(IStorageCacheListener::onAttached); } @Override public void sort() { storages.sort(IStorage.COMPARATOR); } @Override public IStackList getList() { return list; } @Override public IStackList getCraftablesList() { return craftables; } @Override public List getGridStacks() { final List stacks = new ArrayList<>(); for (StackListEntry stack : network.getItemStorageCache().getList().getStacks()) { stacks.add(ItemGridStack.of( stack, network.getItemStorageTracker(), network.getItemStorageCache().getCraftablesList(), false )); } for (StackListEntry stack : network.getItemStorageCache().getCraftablesList().getStacks()) { stacks.add(ItemGridStack.of( stack, network.getItemStorageTracker(), network.getItemStorageCache().getList(), true )); } return stacks; } @Override public List> getStorages() { return storages; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/PortableFluidStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import javax.annotation.Nonnull; import net.neoforged.neoforge.fluids.FluidStack; import java.util.Collections; import java.util.LinkedList; import java.util.List; public class PortableFluidStorageCache implements IStorageCache { private final IPortableGrid portableGrid; private final IStackList list = API.instance().createFluidStackList(); private final List> listeners = new LinkedList<>(); public PortableFluidStorageCache(IPortableGrid portableGrid) { this.portableGrid = portableGrid; } @Override public void invalidate(InvalidateCause cause) { list.clear(); if (portableGrid.getFluidStorage() != null) { portableGrid.getFluidStorage().getStacks().forEach(list::add); } listeners.forEach(IStorageCacheListener::onInvalidated); } @Override public void add(@Nonnull FluidStack stack, int size, boolean rebuilding, boolean batched) { StackListResult result = list.add(stack, size); if (!rebuilding) { listeners.forEach(l -> l.onChanged(result)); } } @Override public void remove(@Nonnull FluidStack stack, int size, boolean batched) { StackListResult result = list.remove(stack, size); if (result != null) { listeners.forEach(l -> l.onChanged(result)); } } @Override public void flush() { throw new UnsupportedOperationException("Cannot flush portable grid storage cache"); } @Override public void addListener(IStorageCacheListener listener) { listeners.add(listener); listener.onAttached(); } @Override public void removeListener(IStorageCacheListener listener) { listeners.remove(listener); } @Override public void reAttachListeners() { listeners.forEach(IStorageCacheListener::onAttached); } @Override public void sort() { // NO OP } @Override public IStackList getList() { return list; } @Override public IStackList getCraftablesList() { throw new UnsupportedOperationException(); } @Override public List getGridStacks() { return portableGrid.getFluidCache().getList().getStacks() .stream() .map(stack -> FluidGridStack.of(stack, portableGrid.getFluidStorageTracker(), null, false)) .toList(); } @Override public List> getStorages() { return Collections.emptyList(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/PortableItemStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache; import com.refinedmods.refinedstorage.api.storage.IStorage; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import java.util.Collections; import java.util.LinkedList; import java.util.List; import javax.annotation.Nonnull; import net.minecraft.world.item.ItemStack; public class PortableItemStorageCache implements IStorageCache { private final IPortableGrid portableGrid; private final IStackList list = API.instance().createItemStackList(); private final List> listeners = new LinkedList<>(); public PortableItemStorageCache(IPortableGrid portableGrid) { this.portableGrid = portableGrid; } @Override public void invalidate(InvalidateCause cause) { list.clear(); if (portableGrid.getItemStorage() != null) { portableGrid.getItemStorage().getStacks().forEach(list::add); } listeners.forEach(IStorageCacheListener::onInvalidated); } @Override public void add(@Nonnull ItemStack stack, int size, boolean rebuilding, boolean batched) { StackListResult result = list.add(stack, size); if (!rebuilding) { listeners.forEach(l -> l.onChanged(result)); } } @Override public void remove(@Nonnull ItemStack stack, int size, boolean batched) { StackListResult result = list.remove(stack, size); if (result != null) { listeners.forEach(l -> l.onChanged(result)); } } @Override public void flush() { throw new UnsupportedOperationException(); } @Override public void addListener(IStorageCacheListener listener) { listeners.add(listener); listener.onAttached(); } @Override public void removeListener(IStorageCacheListener listener) { listeners.remove(listener); } @Override public void reAttachListeners() { listeners.forEach(IStorageCacheListener::onAttached); } @Override public void sort() { // NO OP } @Override public IStackList getList() { return list; } @Override public IStackList getCraftablesList() { throw new UnsupportedOperationException(); } @Override public List getGridStacks() { return portableGrid.getItemCache().getList().getStacks() .stream() .map(stack -> ItemGridStack.of(stack, portableGrid.getItemStorageTracker(), null, false)) .toList(); } @Override public List> getStorages() { return Collections.emptyList(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/FluidGridStorageCacheListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridStackDelta; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import java.util.ArrayList; import java.util.List; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.fluids.FluidStack; public class FluidGridStorageCacheListener implements IStorageCacheListener { private final ServerPlayer player; private final INetwork network; public FluidGridStorageCacheListener(ServerPlayer player, INetwork network) { this.player = player; this.network = network; } @Override public void onAttached() { RS.NETWORK_HANDLER.sendTo(player, new GridFluidUpdateMessage( network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player), (List) network.getFluidStorageCache().getGridStacks() )); } @Override public void onInvalidated() { // NO OP } @Override public void onChanged(StackListResult delta) { List> deltas = new ArrayList<>(); deltas.add(delta); onChangedBulk(deltas); } @Override public void onChangedBulk(List> deltas) { final List> syncDeltas = deltas.stream() .map(delta -> new GridStackDelta<>( delta.getChange(), FluidGridStack.of( network.getFluidStorageCache(), network.getFluidStorageCache().getCraftablesList(), network.getFluidStorageTracker(), delta ) )).toList(); RS.NETWORK_HANDLER.sendTo(player, new GridFluidDeltaMessage(syncDeltas)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/ItemGridStorageCacheListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridStackDelta; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import java.util.ArrayList; import java.util.List; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; public class ItemGridStorageCacheListener implements IStorageCacheListener { private final ServerPlayer player; private final INetwork network; public ItemGridStorageCacheListener(ServerPlayer player, INetwork network) { this.player = player; this.network = network; } @Override public void onAttached() { RS.NETWORK_HANDLER.sendTo(player, new GridItemUpdateMessage( network.getSecurityManager().hasPermission(Permission.AUTOCRAFTING, player), (List) network.getItemStorageCache().getGridStacks() )); } @Override public void onInvalidated() { // NO OP } @Override public void onChanged(StackListResult delta) { List> deltas = new ArrayList<>(); deltas.add(delta); onChangedBulk(deltas); } @Override public void onChangedBulk(List> deltas) { final List> syncDeltas = deltas.stream() .map(delta -> new GridStackDelta<>( delta.getChange(), ItemGridStack.of( network.getItemStorageCache(), network.getItemStorageCache().getCraftablesList(), network.getItemStorageTracker(), delta ) )).toList(); RS.NETWORK_HANDLER.sendTo(player, new GridItemDeltaMessage(syncDeltas)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/PortableFluidGridStorageCacheListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridStackDelta; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.List; public class PortableFluidGridStorageCacheListener implements IStorageCacheListener { private final IPortableGrid portableGrid; private final ServerPlayer player; public PortableFluidGridStorageCacheListener(IPortableGrid portableGrid, ServerPlayer player) { this.portableGrid = portableGrid; this.player = player; } @Override public void onAttached() { RS.NETWORK_HANDLER.sendTo(player, new GridFluidUpdateMessage( false, (List) portableGrid.getFluidCache().getGridStacks() )); } @Override public void onInvalidated() { // NO OP } @Override public void onChanged(StackListResult delta) { List> deltas = new ArrayList<>(); deltas.add(delta); onChangedBulk(deltas); } @Override public void onChangedBulk(List> deltas) { final List> syncDeltas = deltas.stream() .map(delta -> new GridStackDelta<>( delta.getChange(), FluidGridStack.of( portableGrid.getFluidCache(), null, portableGrid.getFluidStorageTracker(), delta ) )).toList(); RS.NETWORK_HANDLER.sendTo(player, new GridFluidDeltaMessage(syncDeltas)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/cache/listener/PortableItemGridStorageCacheListener.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.cache.listener; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.network.grid.GridStackDelta; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import java.util.ArrayList; import java.util.List; public class PortableItemGridStorageCacheListener implements IStorageCacheListener { private final IPortableGrid portableGrid; private final ServerPlayer player; public PortableItemGridStorageCacheListener(IPortableGrid portableGrid, ServerPlayer player) { this.portableGrid = portableGrid; this.player = player; } @Override public void onAttached() { RS.NETWORK_HANDLER.sendTo(player, new GridItemUpdateMessage( false, (List) portableGrid.getItemCache().getGridStacks() )); } @Override public void onInvalidated() { // NO OP } @Override public void onChanged(StackListResult delta) { List> deltas = new ArrayList<>(); deltas.add(delta); onChangedBulk(deltas); } @Override public void onChangedBulk(List> deltas) { final List> syncDeltas = deltas.stream() .map(delta -> new GridStackDelta<>( delta.getChange(), ItemGridStack.of( portableGrid.getItemCache(), null, portableGrid.getItemStorageTracker(), delta ) )).toList(); RS.NETWORK_HANDLER.sendTo(player, new GridItemDeltaMessage(syncDeltas)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/FluidStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class FluidStorageDisk implements IStorageDisk { public static final String NBT_VERSION = "Version"; public static final String NBT_CAPACITY = "Capacity"; public static final String NBT_FLUIDS = "Fluids"; public static final String NBT_OWNER = "Owner"; public static final int VERSION = 1; @Nullable private final ServerLevel level; private final int capacity; private final Multimap stacks = ArrayListMultimap.create(); private final UUID owner; @Nullable private IStorageDiskListener listener; private IStorageDiskContainerContext context; public FluidStorageDisk(@Nullable ServerLevel level, int capacity, @Nullable UUID owner) { this.level = level; this.capacity = capacity; this.owner = owner; } @Override public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); ListTag list = new ListTag(); for (FluidStack stack : stacks.values()) { list.add(stack.writeToNBT(new CompoundTag())); } tag.putInt(NBT_VERSION, VERSION); tag.put(NBT_FLUIDS, list); tag.putInt(NBT_CAPACITY, capacity); if (owner != null) { tag.putUUID(NBT_OWNER, owner); } return tag; } @Override public Collection getStacks() { return stacks.values(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } for (FluidStack otherStack : stacks.get(stack.getFluid())) { if (otherStack.isFluidEqual(stack)) { if (getCapacity() != -1 && getStored() + size > getCapacity()) { int remainingSpace = getCapacity() - getStored(); if (remainingSpace <= 0) { return StackUtils.copy(stack, size); } if (action == Action.PERFORM) { otherStack.grow(remainingSpace); onChanged(); } return StackUtils.copy(otherStack, size - remainingSpace); } else { int maxConsumable = Math.min(size, Integer.MAX_VALUE - otherStack.getAmount()); if (action == Action.PERFORM) { otherStack.grow(maxConsumable); onChanged(); } return StackUtils.copy(otherStack, size - maxConsumable); } } } if (getCapacity() != -1 && getStored() + size > getCapacity()) { int remainingSpace = getCapacity() - getStored(); if (remainingSpace <= 0) { return StackUtils.copy(stack, size); } if (action == Action.PERFORM) { stacks.put(stack.getFluid(), StackUtils.copy(stack, remainingSpace)); onChanged(); } return StackUtils.copy(stack, size - remainingSpace); } else { if (action == Action.PERFORM) { stacks.put(stack.getFluid(), StackUtils.copy(stack, size)); onChanged(); } return FluidStack.EMPTY; } } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { if (stack.isEmpty()) { return stack; } for (FluidStack otherStack : stacks.get(stack.getFluid())) { if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { if (size > otherStack.getAmount()) { size = otherStack.getAmount(); } if (action == Action.PERFORM) { if (otherStack.getAmount() - size == 0) { stacks.remove(otherStack.getFluid(), otherStack); } else { otherStack.shrink(size); } onChanged(); } return StackUtils.copy(otherStack, size); } } return FluidStack.EMPTY; } @Override public int getStored() { return stacks.values().stream().mapToInt(FluidStack::getAmount).sum(); } @Override public int getPriority() { return 0; } @Override public AccessType getAccessType() { return context.getAccessType(); } @Override public int getCapacity() { return capacity; } @Nullable @Override public UUID getOwner() { return owner; } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { if (getAccessType() == AccessType.INSERT) { return 0; } return remainder == null ? size : (size - remainder.getAmount()); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { this.listener = listener; this.context = context; } @Override public ResourceLocation getFactoryId() { return FluidStorageDiskFactory.ID; } public Multimap getRawStacks() { return stacks; } private void onChanged() { if (listener != null) { listener.onChanged(); } if (level != null) { API.instance().getStorageDiskManager(level).markForSaving(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/ItemStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class ItemStorageDisk implements IStorageDisk { public static final String NBT_VERSION = "Version"; public static final String NBT_CAPACITY = "Capacity"; public static final String NBT_ITEMS = "Items"; public static final String NBT_OWNER = "Owner"; public static final int VERSION = 1; @Nullable private final ServerLevel level; private final int capacity; private final Multimap stacks = ArrayListMultimap.create(); private final UUID owner; private int itemCount; @Nullable private IStorageDiskListener listener; private IStorageDiskContainerContext context; public ItemStorageDisk(@Nullable ServerLevel level, int capacity, @Nullable UUID owner) { this.level = level; this.capacity = capacity; this.owner = owner; } @Override public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); ListTag list = new ListTag(); for (ItemStack stack : stacks.values()) { list.add(StackUtils.serializeStackToNbt(stack)); } tag.putInt(NBT_VERSION, VERSION); tag.put(NBT_ITEMS, list); tag.putInt(NBT_CAPACITY, capacity); if (owner != null) { tag.putUUID(NBT_OWNER, owner); } return tag; } @Override public ResourceLocation getFactoryId() { return ItemStorageDiskFactory.ID; } @Override public Collection getStacks() { return stacks.values(); } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { if (stack.isEmpty() || itemCount == capacity) { return ItemHandlerHelper.copyStackWithSize(stack, size); } for (ItemStack otherStack : stacks.get(stack.getItem())) { if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) { if (getCapacity() != -1 && getStored() + size > getCapacity()) { int remainingSpace = getCapacity() - getStored(); if (remainingSpace <= 0) { return ItemHandlerHelper.copyStackWithSize(stack, size); } if (action == Action.PERFORM) { otherStack.grow(remainingSpace); itemCount += remainingSpace; onChanged(); } return ItemHandlerHelper.copyStackWithSize(otherStack, size - remainingSpace); } else { int maxConsumable = Math.min(size, Integer.MAX_VALUE - otherStack.getCount()); if (action == Action.PERFORM) { otherStack.grow(maxConsumable); itemCount += maxConsumable; onChanged(); } return ItemHandlerHelper.copyStackWithSize(otherStack, size - maxConsumable); } } } if (getCapacity() != -1 && getStored() + size > getCapacity()) { int remainingSpace = getCapacity() - getStored(); if (remainingSpace <= 0) { return ItemHandlerHelper.copyStackWithSize(stack, size); } if (action == Action.PERFORM) { stacks.put(stack.getItem(), ItemHandlerHelper.copyStackWithSize(stack, remainingSpace)); itemCount += remainingSpace; onChanged(); } return ItemHandlerHelper.copyStackWithSize(stack, size - remainingSpace); } else { if (action == Action.PERFORM) { stacks.put(stack.getItem(), ItemHandlerHelper.copyStackWithSize(stack, size)); itemCount += size; onChanged(); } return ItemStack.EMPTY; } } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { if (stack.isEmpty()) { return stack; } for (ItemStack otherStack : stacks.get(stack.getItem())) { if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { if (size > otherStack.getCount()) { size = otherStack.getCount(); } if (action == Action.PERFORM) { if (otherStack.getCount() - size == 0) { stacks.remove(otherStack.getItem(), otherStack); } else { otherStack.shrink(size); } itemCount -= size; onChanged(); } return ItemHandlerHelper.copyStackWithSize(otherStack, size); } } return ItemStack.EMPTY; } @Override public int getStored() { return itemCount; } @Override public int getPriority() { return 0; } @Override public AccessType getAccessType() { return context.getAccessType(); } @Override public int getCapacity() { return capacity; } @Nullable @Override public UUID getOwner() { return owner; } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { this.listener = listener; this.context = context; } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { if (getAccessType() == AccessType.INSERT) { return 0; } return remainder == null ? size : (size - remainder.getCount()); } public Multimap getRawStacks() { return stacks; } private void onChanged() { if (listener != null) { listener.onChanged(); } if (level != null) { API.instance().getStorageDiskManager(level).markForSaving(); } } public void updateItemCount() { itemCount = stacks.values().stream().mapToInt(ItemStack::getCount).sum(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/PortableFluidStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class PortableFluidStorageDisk implements IStorageDisk { private final IStorageDisk parent; private final IPortableGrid portableGrid; public PortableFluidStorageDisk(IStorageDisk parent, IPortableGrid portableGrid) { this.parent = parent; this.portableGrid = portableGrid; } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { int storedPre = parent.getStored(); FluidStack remainder = parent.insert(stack, size, action); if (action == Action.PERFORM) { int inserted = parent.getCacheDelta(storedPre, size, remainder); if (inserted > 0) { portableGrid.getFluidCache().add(stack, inserted, false, false); } } return remainder; } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { FluidStack extracted = parent.extract(stack, size, flags, action); if (action == Action.PERFORM && !extracted.isEmpty()) { portableGrid.getFluidCache().remove(extracted, extracted.getAmount(), false); } return extracted; } @Override public int getStored() { return parent.getStored(); } @Override public int getPriority() { return parent.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/PortableItemStorageDisk.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskListener; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.UUID; public class PortableItemStorageDisk implements IStorageDisk { private final IStorageDisk parent; private final IPortableGrid portableGrid; public PortableItemStorageDisk(IStorageDisk parent, IPortableGrid portableGrid) { this.parent = parent; this.portableGrid = portableGrid; } @Override public int getCapacity() { return parent.getCapacity(); } @Nullable @Override public UUID getOwner() { return parent.getOwner(); } @Override public void setSettings(@Nullable IStorageDiskListener listener, IStorageDiskContainerContext context) { parent.setSettings(listener, context); } @Override public CompoundTag writeToNbt() { return parent.writeToNbt(); } @Override public Collection getStacks() { return parent.getStacks(); } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { int storedPre = parent.getStored(); ItemStack remainder = parent.insert(stack, size, action); if (action == Action.PERFORM) { int inserted = parent.getCacheDelta(storedPre, size, remainder); if (inserted > 0) { portableGrid.getItemCache().add(stack, inserted, false, false); } } return remainder; } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { ItemStack extracted = parent.extract(stack, size, flags, action); if (action == Action.PERFORM && !extracted.isEmpty()) { portableGrid.getItemCache().remove(extracted, extracted.getCount(), false); } return extracted; } @Override public int getStored() { return parent.getStored(); } @Override public int getPriority() { return parent.getPriority(); } @Override public AccessType getAccessType() { return parent.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { return parent.getCacheDelta(storedPreInsertion, size, remainder); } @Override public ResourceLocation getFactoryId() { return parent.getFactoryId(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskManager; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.util.RSSavedData; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class StorageDiskManager extends RSSavedData implements IStorageDiskManager { public static final String NAME = "refinedstorage_disks"; private static final String NBT_DISKS = "Disks"; private static final String NBT_DISK_ID = "Id"; private static final String NBT_DISK_TYPE = "Type"; private static final String NBT_DISK_DATA = "Data"; private final Map disks = new HashMap<>(); private final ServerLevel level; public StorageDiskManager(ServerLevel level) { this.level = level; } @Override @Nullable public IStorageDisk get(UUID id) { return disks.get(id); } @Nullable @Override public IStorageDisk getByStack(ItemStack disk) { if (!(disk.getItem() instanceof IStorageDiskProvider)) { return null; } IStorageDiskProvider provider = (IStorageDiskProvider) disk.getItem(); if (!provider.isValid(disk)) { return null; } return get(provider.getId(disk)); } @Override public Map getAll() { return disks; } @Override public void set(UUID id, IStorageDisk disk) { if (id == null) { throw new IllegalArgumentException("Id cannot be null"); } if (disk == null) { throw new IllegalArgumentException("Disk cannot be null"); } if (disks.containsKey(id)) { throw new IllegalArgumentException("Disks already contains id '" + id + "'"); } disks.put(id, disk); } @Override public void remove(UUID id) { if (id == null) { throw new IllegalArgumentException("Id cannot be null"); } disks.remove(id); } @Override public void markForSaving() { setDirty(); } @Override public void load(CompoundTag tag) { if (tag.contains(NBT_DISKS)) { ListTag disksTag = tag.getList(NBT_DISKS, Tag.TAG_COMPOUND); for (int i = 0; i < disksTag.size(); ++i) { CompoundTag diskTag = disksTag.getCompound(i); UUID id = diskTag.getUUID(NBT_DISK_ID); CompoundTag data = diskTag.getCompound(NBT_DISK_DATA); String type = diskTag.getString(NBT_DISK_TYPE); IStorageDiskFactory factory = API.instance().getStorageDiskRegistry().get(new ResourceLocation(type)); if (factory != null) { disks.put(id, factory.createFromNbt(level, data)); } } } } @Override public CompoundTag save(CompoundTag tag) { ListTag disksTag = new ListTag(); for (Map.Entry entry : disks.entrySet()) { CompoundTag diskTag = new CompoundTag(); diskTag.putUUID(NBT_DISK_ID, entry.getKey()); diskTag.put(NBT_DISK_DATA, entry.getValue().writeToNbt()); diskTag.putString(NBT_DISK_TYPE, entry.getValue().getFactoryId().toString()); disksTag.add(diskTag); } tag.put(NBT_DISKS, disksTag); return tag; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskRegistry.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskRegistry; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class StorageDiskRegistry implements IStorageDiskRegistry { private final Map factories = new HashMap<>(); @Override public void add(ResourceLocation id, IStorageDiskFactory factory) { factories.put(id, factory); } @Override @Nullable public IStorageDiskFactory get(ResourceLocation id) { return factories.get(id); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/StorageDiskSync.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskSync; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.network.disk.StorageDiskSizeRequestMessage; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class StorageDiskSync implements IStorageDiskSync { private static final int THROTTLE_MS = 500; private final Map data = new HashMap<>(); private final Map syncTime = new HashMap<>(); @Nullable @Override public StorageDiskSyncData getData(UUID id) { return data.get(id); } public void setData(UUID id, StorageDiskSyncData data) { this.data.put(id, data); } @Override public void sendRequest(UUID id) { long lastSync = syncTime.getOrDefault(id, 0L); if (System.currentTimeMillis() - lastSync > THROTTLE_MS) { RS.NETWORK_HANDLER.sendToServer(new StorageDiskSizeRequestMessage(id)); syncTime.put(id, System.currentTimeMillis()); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/factory/FluidStorageDiskFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.disk.FluidStorageDisk; import com.refinedmods.refinedstorage.item.FluidStorageDiskItem; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.UUID; public class FluidStorageDiskFactory implements IStorageDiskFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "fluid"); @Override public IStorageDisk createFromNbt(ServerLevel level, CompoundTag tag) { FluidStorageDisk disk = new FluidStorageDisk( level, tag.getInt(FluidStorageDisk.NBT_CAPACITY), tag.contains(FluidStorageDisk.NBT_OWNER) ? tag.getUUID(FluidStorageDisk.NBT_OWNER) : null ); ListTag list = tag.getList(FluidStorageDisk.NBT_FLUIDS, Tag.TAG_COMPOUND); for (int i = 0; i < list.size(); ++i) { FluidStack stack = FluidStack.loadFluidStackFromNBT(list.getCompound(i)); if (!stack.isEmpty()) { disk.getRawStacks().put(stack.getRawFluid(), stack); } } return disk; } @Override public ItemStack createDiskItem(IStorageDisk disk, UUID id) { FluidStorageDiskItem item; switch (disk.getCapacity()) { case 64_000: item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.SIXTY_FOUR_K).get(); break; case 256_000: item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K).get(); break; case 1024_000: item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.THOUSAND_TWENTY_FOUR_K).get(); break; case 4096_000: item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K).get(); break; default: item = RSItems.FLUID_STORAGE_DISKS.get(FluidStorageType.CREATIVE).get(); break; } ItemStack stack = new ItemStack(item); item.setId(stack, id); return stack; } @Override public IStorageDisk create(ServerLevel level, int capacity, @Nullable UUID owner) { return new FluidStorageDisk(level, capacity, owner); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/disk/factory/ItemStorageDiskFactory.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.disk.factory; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.disk.ItemStorageDisk; import com.refinedmods.refinedstorage.item.StorageDiskItem; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; import java.util.UUID; public class ItemStorageDiskFactory implements IStorageDiskFactory { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "item"); @Override public IStorageDisk createFromNbt(ServerLevel level, CompoundTag tag) { ItemStorageDisk disk = new ItemStorageDisk( level, tag.getInt(ItemStorageDisk.NBT_CAPACITY), tag.contains(ItemStorageDisk.NBT_OWNER) ? tag.getUUID(ItemStorageDisk.NBT_OWNER) : null ); ListTag list = tag.getList(ItemStorageDisk.NBT_ITEMS, Tag.TAG_COMPOUND); for (int i = 0; i < list.size(); ++i) { ItemStack stack = StackUtils.deserializeStackFromNbt(list.getCompound(i)); if (!stack.isEmpty()) { disk.getRawStacks().put(stack.getItem(), stack); } } disk.updateItemCount(); return disk; } @Override public ItemStack createDiskItem(IStorageDisk disk, UUID id) { StorageDiskItem item; switch (disk.getCapacity()) { case 1_000: item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.ONE_K).get(); break; case 4_000: item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.FOUR_K).get(); break; case 16_000: item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.SIXTEEN_K).get(); break; case 64_000: item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.SIXTY_FOUR_K).get(); break; default: item = RSItems.ITEM_STORAGE_DISKS.get(ItemStorageType.CREATIVE).get(); break; } ItemStack stack = new ItemStack(item); item.setId(stack, id); return stack; } @Override public IStorageDisk create(ServerLevel level, int capacity, @Nullable UUID owner) { return new ItemStorageDisk(level, capacity, owner); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorage.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.util.StackUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.function.Supplier; public class FluidExternalStorage implements IExternalStorage { private final IExternalStorageContext context; private final Supplier handlerSupplier; private final boolean connectedToInterface; private final FluidExternalStorageCache cache = new FluidExternalStorageCache(); public FluidExternalStorage(IExternalStorageContext context, Supplier handlerSupplier, boolean connectedToInterface) { this.context = context; this.handlerSupplier = handlerSupplier; this.connectedToInterface = connectedToInterface; } public boolean isConnectedToInterface() { return connectedToInterface; } @Override public void update(INetwork network) { if (getAccessType() == AccessType.INSERT) { return; } cache.update(network, handlerSupplier.get()); } @Override public long getCapacity() { IFluidHandler fluidHandler = handlerSupplier.get(); if (fluidHandler != null) { long cap = 0; for (int i = 0; i < fluidHandler.getTanks(); ++i) { cap += fluidHandler.getTankCapacity(i); } return cap; } return 0; } @Override public Collection getStacks() { IFluidHandler fluidHandler = handlerSupplier.get(); if (fluidHandler != null) { cache.initCache(fluidHandler); List fluids = new ArrayList<>(); for (int i = 0; i < fluidHandler.getTanks(); ++i) { fluids.add(fluidHandler.getFluidInTank(i)); } return fluids; } return Collections.emptyList(); } @Override @Nonnull public FluidStack insert(@Nonnull FluidStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } IFluidHandler handler = handlerSupplier.get(); if (context.acceptsFluid(stack) && handler != null) { int filled = handler.fill(StackUtils.copy(stack, size), action == Action.PERFORM ? IFluidHandler.FluidAction.EXECUTE : IFluidHandler.FluidAction.SIMULATE); if (filled == size) { return FluidStack.EMPTY; } return StackUtils.copy(stack, size - filled); } return StackUtils.copy(stack, size); } @Override @Nonnull public FluidStack extract(@Nonnull FluidStack stack, int size, int flags, Action action) { if (stack.isEmpty()) { return stack; } IFluidHandler handler = handlerSupplier.get(); if (handler == null) { return FluidStack.EMPTY; } return handler.drain(StackUtils.copy(stack, size), action == Action.PERFORM ? IFluidHandler.FluidAction.EXECUTE : IFluidHandler.FluidAction.SIMULATE); } @Override public int getStored() { return cache.getStored(); } @Override public int getPriority() { return context.getPriority(); } @Override public AccessType getAccessType() { return context.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable FluidStack remainder) { if (getAccessType() == AccessType.INSERT) { return 0; } return remainder == null ? size : (size - remainder.getAmount()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import javax.annotation.Nullable; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import java.util.ArrayList; import java.util.List; public class FluidExternalStorageCache { private List cache; private int stored = 0; public int getStored() { return stored; } public boolean initCache(IFluidHandler handler) { if (cache != null) { return false; } cache = new ArrayList<>(); int stored = 0; for (int i = 0; i < handler.getTanks(); ++i) { FluidStack stack = handler.getFluidInTank(i).copy(); cache.add(stack); stored += stack.getAmount(); } this.stored = stored; return true; } public void update(INetwork network, @Nullable IFluidHandler handler) { if (handler == null) { stored = 0; return; } if (initCache(handler)) { return; } int stored = 0; for (int i = 0; i < handler.getTanks(); ++i) { FluidStack actual = handler.getFluidInTank(i); stored += actual.getAmount(); if (i >= cache.size()) { // ENLARGED if (!actual.isEmpty()) { network.getFluidStorageCache().add(actual, actual.getAmount(), false, true); cache.add(actual.copy()); } continue; } FluidStack cached = cache.get(i); if (actual.isEmpty() && cached.isEmpty()) { // NONE continue; } if (actual.isEmpty() && !cached.isEmpty()) { // REMOVED network.getFluidStorageCache().remove(cached, cached.getAmount(), true); cache.set(i, FluidStack.EMPTY); } else if (!actual.isEmpty() && cached.isEmpty()) { // ADDED network.getFluidStorageCache().add(actual, actual.getAmount(), false, true); cache.set(i, actual.copy()); } else if (!API.instance().getComparer().isEqual(actual, cached, IComparer.COMPARE_NBT)) { // CHANGED network.getFluidStorageCache().remove(cached, cached.getAmount(), true); network.getFluidStorageCache().add(actual, actual.getAmount(), false, true); cache.set(i, actual.copy()); } else if (actual.getAmount() > cached.getAmount()) { // COUNT_CHANGED network.getFluidStorageCache().add(actual, actual.getAmount() - cached.getAmount(), false, true); cached.setAmount(actual.getAmount()); } else if (actual.getAmount() < cached.getAmount()) { // COUNT_CHANGED network.getFluidStorageCache().remove(actual, cached.getAmount() - actual.getAmount(), true); cached.setAmount(actual.getAmount()); } } this.stored = stored; if (cache.size() > handler.getTanks()) { // SHRUNK for (int i = cache.size() - 1; i >= handler.getTanks(); --i) { // Reverse order for the remove call. FluidStack cached = cache.get(i); if (!cached.isEmpty()) { network.getFluidStorageCache().remove(cached, cached.getAmount(), true); } cache.remove(i); } } network.getFluidStorageCache().flush(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/FluidExternalStorageProvider.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; public class FluidExternalStorageProvider implements IExternalStorageProvider { @Override public boolean canProvide(Level level, BlockPos pos, Direction direction) { return LevelUtils.getFluidHandler(level, pos, direction.getOpposite()) != null; } @Nonnull @Override public IExternalStorage provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction) { return new FluidExternalStorage(context, () -> { Level level = blockEntity.getLevel(); if (level == null) { return null; } return LevelUtils.getFluidHandler(level, blockEntity.getBlockPos(), direction.getOpposite()); }, blockEntity instanceof FluidInterfaceBlockEntity); } @Override public int getPriority() { return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorage.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.function.Supplier; public class ItemExternalStorage implements IExternalStorage { private final IExternalStorageContext context; private final Supplier handlerSupplier; private final boolean connectedToInterface; private final ItemExternalStorageCache cache = new ItemExternalStorageCache(); public ItemExternalStorage(IExternalStorageContext context, Supplier handlerSupplier, boolean connectedToInterface) { this.context = context; this.handlerSupplier = handlerSupplier; this.connectedToInterface = connectedToInterface; } public boolean isConnectedToInterface() { return connectedToInterface; } @Override public void update(INetwork network) { if (getAccessType() == AccessType.INSERT) { return; } cache.update(network, handlerSupplier.get()); } @Override public long getCapacity() { IItemHandler handler = handlerSupplier.get(); if (handler == null) { return 0; } long capacity = 0; for (int i = 0; i < handler.getSlots(); ++i) { capacity += handler.getSlotLimit(i); } return capacity; } @Override public Collection getStacks() { IItemHandler handler = handlerSupplier.get(); if (handler == null) { return Collections.emptyList(); } cache.initCache(handler); List stacks = new ArrayList<>(); for (int i = 0; i < handler.getSlots(); ++i) { stacks.add(handler.getStackInSlot(i)); } return stacks; } @Override @Nonnull public ItemStack insert(@Nonnull ItemStack stack, int size, Action action) { if (stack.isEmpty()) { return stack; } IItemHandler handler = handlerSupplier.get(); if (handler != null && context.acceptsItem(stack)) { return ItemHandlerHelper.insertItem(handler, ItemHandlerHelper.copyStackWithSize(stack, size), action == Action.SIMULATE); } return ItemHandlerHelper.copyStackWithSize(stack, size); } @Override @Nonnull public ItemStack extract(@Nonnull ItemStack stack, int size, int flags, Action action) { if (stack.isEmpty()) { return stack; } IItemHandler handler = handlerSupplier.get(); if (handler == null) { return ItemStack.EMPTY; } int remaining = size; ItemStack received = ItemStack.EMPTY; for (int i = 0; i < handler.getSlots(); ++i) { ItemStack slot = handler.getStackInSlot(i); if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, flags)) { ItemStack got = handler.extractItem(i, remaining, action == Action.SIMULATE); if (!got.isEmpty()) { if (received.isEmpty()) { received = got.copy(); } else { received.grow(got.getCount()); } remaining -= got.getCount(); if (remaining == 0) { break; } } } } return received; } @Override public int getStored() { return cache.getStored(); } @Override public int getPriority() { return context.getPriority(); } @Override public AccessType getAccessType() { return context.getAccessType(); } @Override public int getCacheDelta(int storedPreInsertion, int size, @Nullable ItemStack remainder) { if (getAccessType() == AccessType.INSERT) { return 0; } return remainder == null ? size : (size - remainder.getCount()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorageCache.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class ItemExternalStorageCache { private List cache; private int stored = 0; public int getStored() { return stored; } public boolean initCache(IItemHandler handler) { if (cache != null) { return false; } cache = new ArrayList<>(); int stored = 0; for (int i = 0; i < handler.getSlots(); ++i) { ItemStack stack = handler.getStackInSlot(i).copy(); cache.add(stack); stored += stack.getCount(); } this.stored = stored; return true; } public void update(INetwork network, @Nullable IItemHandler handler) { if (handler == null) { stored = 0; return; } if (initCache(handler)) { return; } int stored = 0; for (int i = 0; i < handler.getSlots(); ++i) { ItemStack actual = handler.getStackInSlot(i); stored += actual.getCount(); if (i >= cache.size()) { // ENLARGED if (!actual.isEmpty()) { network.getItemStorageCache().add(actual, actual.getCount(), false, true); cache.add(actual.copy()); } continue; } ItemStack cached = cache.get(i); //ItemStack.EMPTY can be accidentally modified by other mods on any thread. This makes sure we ignore that. if (actual == ItemStack.EMPTY && actual == cached) continue; if (!cached.isEmpty() && actual.isEmpty()) { // REMOVED network.getItemStorageCache().remove(cached, cached.getCount(), true); cache.set(i, ItemStack.EMPTY); } else if (cached.isEmpty() && !actual.isEmpty()) { // ADDED network.getItemStorageCache().add(actual, actual.getCount(), false, true); cache.set(i, actual.copy()); } else if (!API.instance().getComparer().isEqualNoQuantity(cached, actual)) { // CHANGED network.getItemStorageCache().remove(cached, cached.getCount(), true); network.getItemStorageCache().add(actual, actual.getCount(), false, true); cache.set(i, actual.copy()); } else if (cached.getCount() != actual.getCount()) { // COUNT_CHANGED int delta = actual.getCount() - cached.getCount(); if (delta > 0) { network.getItemStorageCache().add(actual, delta, false, true); cached.grow(delta); } else { network.getItemStorageCache().remove(actual, Math.abs(delta), true); cached.shrink(Math.abs(delta)); } } } this.stored = stored; if (cache.size() > handler.getSlots()) { // SHRUNK for (int i = cache.size() - 1; i >= handler.getSlots(); --i) { // Reverse order for the remove call. ItemStack cached = cache.get(i); if (!cached.isEmpty()) { network.getItemStorageCache().remove(cached, cached.getCount(), true); } cache.remove(i); } } network.getItemStorageCache().flush(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/externalstorage/ItemExternalStorageProvider.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.externalstorage; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.storage.IStorageProvider; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageContext; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorageProvider; import com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nonnull; public class ItemExternalStorageProvider implements IExternalStorageProvider { @Override public boolean canProvide(Level level, BlockPos pos, Direction direction) { INetworkNode node = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(pos)); if (node instanceof IStorageProvider) { return false; } return LevelUtils.getItemHandler(level, pos, direction.getOpposite()) != null; } @Nonnull @Override public IExternalStorage provide(IExternalStorageContext context, BlockEntity blockEntity, Direction direction) { return new ItemExternalStorage(context, () -> { Level level = blockEntity.getLevel(); if (level == null) { return null; } return LevelUtils.getItemHandler(level, blockEntity.getBlockPos(), direction.getOpposite()); }, blockEntity instanceof InterfaceBlockEntity); } @Override public int getPriority() { return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/FluidStorageTracker.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.tracker; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.fluids.FluidStack; import java.util.HashMap; import java.util.Map; public class FluidStorageTracker implements IStorageTracker { private static final String NBT_STACK = "Stack"; private static final String NBT_NAME = "Name"; private static final String NBT_TIME = "Time"; private final Map changes = new HashMap<>(); private final Runnable listener; public FluidStorageTracker(Runnable listener) { this.listener = listener; } @Override public void changed(Player player, FluidStack stack) { changes.put(new Key(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString())); listener.run(); } @Override public StorageTrackerEntry get(FluidStack stack) { return changes.get(new Key(stack)); } @Override public void readFromNbt(ListTag list) { for (int i = 0; i < list.size(); ++i) { CompoundTag tag = list.getCompound(i); FluidStack stack = FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_STACK)); if (!stack.isEmpty()) { changes.put(new Key(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME))); } } } @Override public ListTag serializeNbt() { ListTag list = new ListTag(); for (Map.Entry entry : changes.entrySet()) { CompoundTag tag = new CompoundTag(); tag.putLong(NBT_TIME, entry.getValue().getTime()); tag.putString(NBT_NAME, entry.getValue().getName()); tag.put(NBT_STACK, entry.getKey().stack.writeToNBT(new CompoundTag())); list.add(tag); } return list; } private static class Key { private final FluidStack stack; public Key(FluidStack stack) { this.stack = stack; } @Override public boolean equals(Object other) { return other instanceof Key && API.instance().getComparer().isEqual(stack, ((Key) other).stack, IComparer.COMPARE_NBT); } @Override public int hashCode() { return API.instance().getFluidStackHashCode(stack); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/ItemStorageTracker.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.tracker; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.util.ItemStackKey; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import java.util.HashMap; import java.util.Map; public class ItemStorageTracker implements IStorageTracker { private static final String NBT_STACK = "Stack"; private static final String NBT_NAME = "Name"; private static final String NBT_TIME = "Time"; private final Map changes = new HashMap<>(); private final Runnable listener; public ItemStorageTracker(Runnable listener) { this.listener = listener; } @Override public void changed(Player player, ItemStack stack) { changes.put(new ItemStackKey(stack), new StorageTrackerEntry(System.currentTimeMillis(), player.getName().getString())); listener.run(); } @Override public StorageTrackerEntry get(ItemStack stack) { return changes.get(new ItemStackKey(stack)); } @Override public void readFromNbt(ListTag list) { for (int i = 0; i < list.size(); ++i) { CompoundTag tag = list.getCompound(i); ItemStack stack = StackUtils.deserializeStackFromNbt(tag.getCompound(NBT_STACK)); if (!stack.isEmpty()) { changes.put(new ItemStackKey(stack), new StorageTrackerEntry(tag.getLong(NBT_TIME), tag.getString(NBT_NAME))); } } } @Override public ListTag serializeNbt() { ListTag list = new ListTag(); for (Map.Entry entry : changes.entrySet()) { CompoundTag tag = new CompoundTag(); tag.putLong(NBT_TIME, entry.getValue().getTime()); tag.putString(NBT_NAME, entry.getValue().getName()); tag.put(NBT_STACK, StackUtils.serializeStackToNbt(entry.getKey().getStack())); list.add(tag); } return list; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/storage/tracker/StorageTrackerManager.java ================================================ package com.refinedmods.refinedstorage.apiimpl.storage.tracker; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTrackerManager; import com.refinedmods.refinedstorage.apiimpl.util.RSSavedData; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class StorageTrackerManager extends RSSavedData implements IStorageTrackerManager { public static final String NAME = "refinedstorage_tracker"; private static final String NBT_TRACKERS = "Tracker"; private static final String NBT_TRACKER_ID = "Id"; private static final String NBT_TRACKER_DATA = "Data"; private static final String NBT_TRACKER_TYPE = "Type"; private final Map> trackers = new HashMap<>(); @Override public void markForSaving() { this.setDirty(); } @Override public IStorageTracker getOrCreate(UUID uuid, StorageType type) { IStorageTracker tracker = trackers.get(uuid); if (tracker == null) { if (type == StorageType.ITEM) { tracker = new ItemStorageTracker(this::markForSaving); } else if (type == StorageType.FLUID) { tracker = new FluidStorageTracker(this::markForSaving); } trackers.put(uuid, tracker); } return tracker; } @Override public void remove(UUID id) { trackers.remove(id); } @Override public void load(CompoundTag nbt) { if (nbt.contains(NBT_TRACKERS)) { ListTag trackerTags = nbt.getList(NBT_TRACKERS, Tag.TAG_COMPOUND); for (int i = 0; i < trackerTags.size(); ++i) { CompoundTag trackerTag = trackerTags.getCompound(i); UUID id = trackerTag.getUUID(NBT_TRACKER_ID); ListTag data = trackerTag.getList(NBT_TRACKER_DATA, Tag.TAG_COMPOUND); StorageType type = StorageType.values()[trackerTag.getInt(NBT_TRACKER_TYPE)]; IStorageTracker tracker = getOrCreate(id, type); tracker.readFromNbt(data); } } } @Override public CompoundTag save(CompoundTag compound) { ListTag trackerListTag = new ListTag(); for (Map.Entry> entry : trackers.entrySet()) { CompoundTag trackerTag = new CompoundTag(); trackerTag.putUUID(NBT_TRACKER_ID, entry.getKey()); trackerTag.put(NBT_TRACKER_DATA, entry.getValue().serializeNbt()); trackerTag.putInt(NBT_TRACKER_TYPE, entry.getValue() instanceof ItemStorageTracker ? StorageType.ITEM.ordinal() : StorageType.FLUID.ordinal()); trackerListTag.add(trackerTag); } compound.put(NBT_TRACKERS, trackerListTag); return compound; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/Comparer.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.refinedmods.refinedstorage.api.util.IComparer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; public class Comparer implements IComparer { @Override public boolean isEqual(@Nonnull ItemStack left, @Nonnull ItemStack right, int flags) { if (left.isEmpty() && right.isEmpty()) { return true; } if (!ItemStack.isSameItem(left, right)) { return false; } if ((flags & COMPARE_NBT) == COMPARE_NBT && !ItemStack.isSameItemSameTags(left, right)) { return false; } if ((flags & COMPARE_QUANTITY) == COMPARE_QUANTITY && left.getCount() != right.getCount()) { return false; } return true; } @Override public boolean isEqual(@Nonnull FluidStack left, @Nonnull FluidStack right, int flags) { if (left.isEmpty() && right.isEmpty()) { return true; } if (left.getFluid() != right.getFluid()) { return false; } if ((flags & COMPARE_NBT) == COMPARE_NBT && !FluidStack.areFluidStackTagsEqual(left, right)) { return false; } if ((flags & COMPARE_QUANTITY) == COMPARE_QUANTITY && left.getAmount() != right.getAmount()) { return false; } return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/FluidFilter.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.refinedmods.refinedstorage.api.util.IFilter; import net.neoforged.neoforge.fluids.FluidStack; public class FluidFilter implements IFilter { private final FluidStack stack; private final int compare; private final int mode; private final boolean modFilter; public FluidFilter(FluidStack stack, int compare, int mode, boolean modFilter) { this.stack = stack; this.compare = compare; this.mode = mode; this.modFilter = modFilter; } @Override public Object getStack() { return stack; } @Override public int getCompare() { return compare; } @Override public int getMode() { return mode; } @Override public boolean isModFilter() { return modFilter; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/FluidStackList.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.google.common.collect.ArrayListMultimap; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class FluidStackList implements IStackList { private final ArrayListMultimap> stacks = ArrayListMultimap.create(); private final Map index = new HashMap<>(); public FluidStackList() { } public FluidStackList(Iterable stacks) { for (FluidStack stack : stacks) { add(stack); } } @Override public StackListResult add(@Nonnull FluidStack stack, int size) { if (stack.isEmpty() || size <= 0) { throw new IllegalArgumentException("Cannot accept empty stack"); } for (StackListEntry entry : stacks.get(stack.getFluid())) { FluidStack otherStack = entry.getStack(); if (stack.isFluidEqual(otherStack)) { if ((long) otherStack.getAmount() + (long) size > Integer.MAX_VALUE) { otherStack.setAmount(Integer.MAX_VALUE); } else { otherStack.grow(size); } return new StackListResult<>(otherStack, entry.getId(), size); } } FluidStack newStack = stack.copy(); newStack.setAmount(size); StackListEntry newEntry = new StackListEntry<>(newStack); stacks.put(newStack.getFluid(), newEntry); index.put(newEntry.getId(), newEntry.getStack()); return new StackListResult<>(newStack, newEntry.getId(), size); } @Override public StackListResult add(@Nonnull FluidStack stack) { return add(stack, stack.getAmount()); } @Override public StackListResult remove(@Nonnull FluidStack stack, int size) { for (StackListEntry entry : stacks.get(stack.getFluid())) { FluidStack otherStack = entry.getStack(); if (stack.isFluidEqual(otherStack)) { if (otherStack.getAmount() - size <= 0) { stacks.remove(otherStack.getFluid(), entry); index.remove(entry.getId()); return new StackListResult<>(otherStack, entry.getId(), -otherStack.getAmount()); } else { otherStack.shrink(size); return new StackListResult<>(otherStack, entry.getId(), -size); } } } return null; } @Override public StackListResult remove(@Nonnull FluidStack stack) { return remove(stack, stack.getAmount()); } @Override public int getCount(@Nonnull FluidStack stack, int flags) { FluidStack found = get(stack, flags); if (found == null) { return 0; } return found.getAmount(); } @Override @Nullable public FluidStack get(@Nonnull FluidStack stack, int flags) { for (StackListEntry entry : stacks.get(stack.getFluid())) { FluidStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { return otherStack; } } return null; } @Nullable @Override public StackListEntry getEntry(@Nonnull FluidStack stack, int flags) { for (StackListEntry entry : stacks.get(stack.getFluid())) { FluidStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { return entry; } } return null; } @Override @Nullable public FluidStack get(UUID id) { return index.get(id); } @Override public void clear() { stacks.clear(); index.clear(); } @Override public boolean isEmpty() { return stacks.isEmpty(); } @Nonnull @Override public Collection> getStacks() { return stacks.values(); } @Override @Nonnull public Collection> getStacks(@Nonnull FluidStack stack) { return stacks.get(stack.getFluid()); } @Override @Nonnull public IStackList copy() { FluidStackList list = new FluidStackList(); for (StackListEntry entry : stacks.values()) { FluidStack newStack = entry.getStack().copy(); list.stacks.put(entry.getStack().getFluid(), new StackListEntry<>(entry.getId(), newStack)); list.index.put(entry.getId(), newStack); } return list; } @Override public int size() { return stacks.size(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/ItemFilter.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.refinedmods.refinedstorage.api.util.IFilter; import net.minecraft.world.item.ItemStack; public class ItemFilter implements IFilter { private final ItemStack stack; private final int compare; private final int mode; private final boolean modFilter; public ItemFilter(ItemStack stack, int compare, int mode, boolean modFilter) { this.stack = stack; this.compare = compare; this.mode = mode; this.modFilter = modFilter; } @Override public Object getStack() { return stack; } @Override public int getCompare() { return compare; } @Override public int getMode() { return mode; } @Override public boolean isModFilter() { return modFilter; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/ItemStackList.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.google.common.collect.ArrayListMultimap; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.UUID; public class ItemStackList implements IStackList { private final ArrayListMultimap> stacks = ArrayListMultimap.create(); private final Map index = new HashMap<>(); public ItemStackList() { } public ItemStackList(Iterable stacks) { for (ItemStack stack : stacks) { add(stack); } } @Override public StackListResult add(@Nonnull ItemStack stack, int size) { if (stack.isEmpty() || size <= 0) { throw new IllegalArgumentException("Cannot accept empty stack"); } for (StackListEntry entry : stacks.get(stack.getItem())) { ItemStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) { if ((long) otherStack.getCount() + (long) size > Integer.MAX_VALUE) { otherStack.setCount(Integer.MAX_VALUE); } else { otherStack.grow(size); } return new StackListResult<>(otherStack, entry.getId(), size); } } StackListEntry newEntry = new StackListEntry<>(ItemHandlerHelper.copyStackWithSize(stack, size)); stacks.put(stack.getItem(), newEntry); index.put(newEntry.getId(), newEntry.getStack()); return new StackListResult<>(newEntry.getStack(), newEntry.getId(), size); } @Override public StackListResult add(@Nonnull ItemStack stack) { return add(stack, stack.getCount()); } @Override public StackListResult remove(@Nonnull ItemStack stack, int size) { for (StackListEntry entry : stacks.get(stack.getItem())) { ItemStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqualNoQuantity(otherStack, stack)) { if (otherStack.getCount() - size <= 0) { stacks.remove(otherStack.getItem(), entry); index.remove(entry.getId()); return new StackListResult<>(otherStack, entry.getId(), -otherStack.getCount()); } else { otherStack.shrink(size); return new StackListResult<>(otherStack, entry.getId(), -size); } } } return null; } @Override public StackListResult remove(@Nonnull ItemStack stack) { return remove(stack, stack.getCount()); } @Override public int getCount(@Nonnull ItemStack stack, int flags) { ItemStack found = get(stack, flags); if (found == null) { return 0; } return found.getCount(); } @Override @Nullable public ItemStack get(@Nonnull ItemStack stack, int flags) { for (StackListEntry entry : stacks.get(stack.getItem())) { ItemStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { return otherStack; } } return null; } @Nullable @Override public StackListEntry getEntry(@Nonnull ItemStack stack, int flags) { for (StackListEntry entry : stacks.get(stack.getItem())) { ItemStack otherStack = entry.getStack(); if (API.instance().getComparer().isEqual(otherStack, stack, flags)) { return entry; } } return null; } @Override @Nullable public ItemStack get(UUID id) { return index.get(id); } @Override public void clear() { stacks.clear(); index.clear(); } @Override public boolean isEmpty() { return stacks.isEmpty(); } @Nonnull @Override public Collection> getStacks() { return stacks.values(); } @Override @Nonnull public Collection> getStacks(@Nonnull ItemStack stack) { return stacks.get(stack.getItem()); } @Override @Nonnull public IStackList copy() { ItemStackList list = new ItemStackList(); for (StackListEntry entry : stacks.values()) { ItemStack newStack = entry.getStack().copy(); list.stacks.put(entry.getStack().getItem(), new StackListEntry<>(entry.getId(), newStack)); list.index.put(entry.getId(), newStack); } return list; } @Override public int size() { return stacks.size(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/QuantityFormatter.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import com.refinedmods.refinedstorage.api.util.IQuantityFormatter; import com.refinedmods.refinedstorage.apiimpl.API; import java.math.RoundingMode; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; import java.util.Locale; import net.neoforged.neoforge.fluids.FluidType; public class QuantityFormatter implements IQuantityFormatter { private final DecimalFormat formatterWithUnits = new DecimalFormat("####0.#", DecimalFormatSymbols.getInstance(Locale.US)); private final DecimalFormat formatter = new DecimalFormat("#,###", DecimalFormatSymbols.getInstance(Locale.US)); private final DecimalFormat bucketFormatter = new DecimalFormat("####0.###", DecimalFormatSymbols.getInstance(Locale.US)); public QuantityFormatter() { formatterWithUnits.setRoundingMode(RoundingMode.DOWN); } @Override public String formatWithUnits(int qty) { return formatWithUnits((long) qty); } @Override public String formatWithUnits(long qty) { if (qty >= 1_000_000_000) { return formatterWithUnits.format(Math.round((float) qty / 1_000_000_000)) + "B"; } else if (qty >= 1_000_000) { float qtyShort = (float) qty / 1_000_000F; if (qty >= 100_000_000) { qtyShort = Math.round(qtyShort); // XXX.XM looks weird. } return formatterWithUnits.format(qtyShort) + "M"; } else if (qty >= 1000) { float qtyShort = (float) qty / 1000F; if (qty >= 100_000) { qtyShort = Math.round(qtyShort); // XXX.XK looks weird. } return formatterWithUnits.format(qtyShort) + "K"; } return String.valueOf(qty); } @Override public String format(int qty) { return formatter.format(qty); } @Override public String format(long qty) { return formatter.format(qty); } @Override public String formatInBucketForm(int qty) { return bucketFormatter.format((float) qty / (float) FluidType.BUCKET_VOLUME) + " B"; } @Override public String formatInBucketFormWithOnlyTrailingDigitsIfZero(int qty) { float amountRaw = ((float) qty / (float) FluidType.BUCKET_VOLUME); int amount = (int) amountRaw; if (amount >= 1) { return API.instance().getQuantityFormatter().formatWithUnits(amount); } else { return String.format("%.1f", amountRaw); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/apiimpl/util/RSSavedData.java ================================================ package com.refinedmods.refinedstorage.apiimpl.util; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtUtils; import net.minecraft.world.level.saveddata.SavedData; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import java.io.File; import java.io.IOException; public abstract class RSSavedData extends SavedData { private final Logger LOGGER = LogManager.getLogger(RSSavedData.class); public abstract void load(CompoundTag nbt); @Override public abstract CompoundTag save(CompoundTag compound); @Override public void save(File file) { // @Volatile Mostly Copied from SavedData if (this.isDirty()) { File tempFile = file.toPath().getParent().resolve(file.getName() + ".temp").toFile(); CompoundTag tag = new CompoundTag(); tag.put("data", this.save(new CompoundTag())); NbtUtils.addCurrentDataVersion(tag); try { NbtIo.writeCompressed(tag, tempFile.toPath()); if (file.exists()) { if (!file.delete()) { LOGGER.error("Failed to delete " + file.getName()); } } if (!tempFile.renameTo(file)) { LOGGER.error("Failed to rename " + tempFile.getName()); } } catch (IOException e) { LOGGER.error("Could not save data {}", this, e); } this.setDirty(false); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/BaseBlock.java ================================================ package com.refinedmods.refinedstorage.block; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; public abstract class BaseBlock extends Block { protected BaseBlock(Properties properties) { super(properties); } public BlockDirection getDirection() { return BlockDirection.NONE; } @Override @SuppressWarnings("deprecation") public BlockState rotate(BlockState state, Rotation rot) { BlockDirection dir = getDirection(); if (dir != BlockDirection.NONE) { Direction newDirection = dir.cycle(state.getValue(dir.getProperty())); return state.setValue(dir.getProperty(), newDirection); } return super.rotate(state, rot); } protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) { // NO OP } @Override @SuppressWarnings("deprecation") public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { super.onRemove(state, level, pos, newState, isMoving); checkIfDirectionHasChanged(state, level, pos, newState); } protected void checkIfDirectionHasChanged(BlockState state, Level level, BlockPos pos, BlockState newState) { if (getDirection() != BlockDirection.NONE && state.getBlock() == newState.getBlock() && state.getValue(getDirection().getProperty()) != newState.getValue(getDirection().getProperty())) { onDirectionChanged(level, pos, newState.getValue(getDirection().getProperty())); } } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); BlockDirection dir = getDirection(); if (dir != BlockDirection.NONE) { builder.add(dir.getProperty()); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/BlockDirection.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.util.DirectionUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.level.block.state.properties.DirectionProperty; import java.util.Arrays; public enum BlockDirection { NONE(), ANY(Direction.values()), ANY_FACE_PLAYER(Direction.values()), HORIZONTAL(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST); private final DirectionProperty property; BlockDirection(Direction... allowed) { this.property = DirectionProperty.create("direction", Arrays.asList(allowed)); } public DirectionProperty getProperty() { return property; } public Direction getFrom(Direction facing, BlockPos pos, LivingEntity entity) { switch (this) { case ANY: return facing.getOpposite(); case ANY_FACE_PLAYER: return DirectionUtils.getFacingFromEntity(pos, entity); case HORIZONTAL: return entity.getDirection().getOpposite(); default: throw new IllegalStateException("Unknown direction type"); } } public Direction cycle(Direction previous) { switch (this) { case ANY: case ANY_FACE_PLAYER: return previous.ordinal() + 1 >= Direction.values().length ? Direction.values()[0] : Direction.values()[previous.ordinal() + 1]; case HORIZONTAL: return previous.getCounterClockWise(); default: throw new IllegalStateException("Unknown direction type"); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/BlockListener.java ================================================ package com.refinedmods.refinedstorage.block; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.event.entity.player.PlayerEvent; public class BlockListener { // Allow break without tool @SubscribeEvent public void onHarvestCheck(PlayerEvent.HarvestCheck e) { if (e.getTargetBlock().getBlock() instanceof BaseBlock) { e.setCanHarvest(true); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/CableBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.blockentity.CableBlockEntity; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.util.BlockUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.material.Fluid; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import javax.annotation.Nullable; import java.util.Optional; public class CableBlock extends NetworkNodeBlock implements SimpleWaterloggedBlock { protected static final VoxelShape HOLDER_NORTH = box(7, 7, 2, 9, 9, 6); protected static final VoxelShape HOLDER_EAST = box(10, 7, 7, 14, 9, 9); protected static final VoxelShape HOLDER_SOUTH = box(7, 7, 10, 9, 9, 14); protected static final VoxelShape HOLDER_WEST = box(2, 7, 7, 6, 9, 9); protected static final VoxelShape HOLDER_UP = box(7, 10, 7, 9, 14, 9); protected static final VoxelShape HOLDER_DOWN = box(7, 2, 7, 9, 6, 9); private static final BooleanProperty NORTH = BooleanProperty.create("north"); private static final BooleanProperty EAST = BooleanProperty.create("east"); private static final BooleanProperty SOUTH = BooleanProperty.create("south"); private static final BooleanProperty WEST = BooleanProperty.create("west"); private static final BooleanProperty UP = BooleanProperty.create("up"); private static final BooleanProperty DOWN = BooleanProperty.create("down"); private static final BooleanProperty WATERLOGGED = BooleanProperty.create("waterlogged"); private static final VoxelShape SHAPE_CORE = box(6, 6, 6, 10, 10, 10); private static final VoxelShape SHAPE_NORTH = box(6, 6, 0, 10, 10, 6); private static final VoxelShape SHAPE_EAST = box(10, 6, 6, 16, 10, 10); private static final VoxelShape SHAPE_SOUTH = box(6, 6, 10, 10, 10, 16); private static final VoxelShape SHAPE_WEST = box(0, 6, 6, 6, 10, 10); private static final VoxelShape SHAPE_UP = box(6, 10, 6, 10, 16, 10); private static final VoxelShape SHAPE_DOWN = box(6, 0, 6, 10, 6, 10); protected CableBlock(Properties props) { super(props); this.registerDefaultState(defaultBlockState().setValue(WATERLOGGED, false)); } public CableBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); this.registerDefaultState(defaultBlockState().setValue(NORTH, false).setValue(EAST, false).setValue(SOUTH, false).setValue(WEST, false).setValue(UP, false).setValue(DOWN, false).setValue(WATERLOGGED, false)); } protected static VoxelShape getCableShape(BlockState state) { VoxelShape shape = SHAPE_CORE; if (Boolean.TRUE.equals(state.getValue(NORTH))) { shape = Shapes.or(shape, SHAPE_NORTH); } if (Boolean.TRUE.equals(state.getValue(EAST))) { shape = Shapes.or(shape, SHAPE_EAST); } if (Boolean.TRUE.equals(state.getValue(SOUTH))) { shape = Shapes.or(shape, SHAPE_SOUTH); } if (Boolean.TRUE.equals(state.getValue(WEST))) { shape = Shapes.or(shape, SHAPE_WEST); } if (Boolean.TRUE.equals(state.getValue(UP))) { shape = Shapes.or(shape, SHAPE_UP); } if (Boolean.TRUE.equals(state.getValue(DOWN))) { shape = Shapes.or(shape, SHAPE_DOWN); } return shape; } public static boolean hasVisualConnectionOnSide(BlockState state, Direction direction) { switch (direction) { case DOWN: return state.getValue(DOWN); case UP: return state.getValue(UP); case NORTH: return state.getValue(NORTH); case SOUTH: return state.getValue(SOUTH); case WEST: return state.getValue(WEST); case EAST: return state.getValue(EAST); } return false; } @Override @SuppressWarnings("deprecation") public BlockState updateShape(BlockState state, Direction dir, BlockState facingState, LevelAccessor world, BlockPos pos, BlockPos facingPos) { return getState(state, world, pos); } @Override @SuppressWarnings("deprecation") public boolean isPathfindable(BlockState state, BlockGetter worldIn, BlockPos pos, PathComputationType type) { return false; } @Override @SuppressWarnings("deprecation") public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, CableBlock::getCableShape), world, pos); } @Override protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) { // rotate() in BaseBlock "stupidly" changes the direction without checking if our cable connections are still valid. // You'd expect that cable connections are not changing when simply changing the direction. // But they need to. For example, when rotating a constructor to connect to a neighboring cable, the connection to that neighbor // needs to be removed as otherwise the "holder" of the constructor will conflict with the cable connection. // This is already checked in hasNode(). // But since rotate() doesn't invalidate that connection, we need to do it here. // 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. level.setBlockAndUpdate(pos, getState(level.getBlockState(pos), level, pos)); //when rotating skip rotations blocked by covers BlockDirection dir = getDirection(); if (dir != BlockDirection.NONE) { if (isSideCovered(level.getBlockEntity(pos), newDirection)) { BlockState newState = rotate(level.getBlockState(pos), Rotation.CLOCKWISE_90); level.setBlockAndUpdate(pos, newState); } } super.onDirectionChanged(level, pos, newDirection); } @Override public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving); level.setBlockAndUpdate(pos, getState(level.getBlockState(pos), level, pos)); } @Nullable @Override public BlockState getStateForPlacement(BlockPlaceContext ctx) { FluidState fluidState = ctx.getLevel().getFluidState(ctx.getClickedPos()); return getState(defaultBlockState().setValue(WATERLOGGED, fluidState.getType() == Fluids.WATER), ctx.getLevel(), ctx.getClickedPos()); } @Override @SuppressWarnings("deprecation") public FluidState getFluidState(BlockState state) { return Boolean.TRUE.equals(state.getValue(WATERLOGGED)) ? Fluids.WATER.getSource(false) : super.getFluidState(state); } @Override public boolean placeLiquid(LevelAccessor world, BlockPos pos, BlockState state, FluidState fluidState) { return SimpleWaterloggedBlock.super.placeLiquid(world, pos, state, fluidState); } @Override public boolean canPlaceLiquid(Player player, BlockGetter world, BlockPos pos, BlockState state, Fluid fluid) { return SimpleWaterloggedBlock.super.canPlaceLiquid(player, world, pos, state, fluid); } private boolean hasNodeConnection(LevelAccessor level, BlockPos pos, BlockState state, Direction direction) { // Prevent the "holder" of a cable block conflicting with a cable connection. if (getDirection() != BlockDirection.NONE && state.getValue(getDirection().getProperty()).getOpposite() == direction) { return false; } BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity == null) { return false; } return level.getBlockEntity(pos) instanceof INetworkNodeProxy && !isSideCovered(blockEntity, direction) && !isSideCovered(level.getBlockEntity(pos.relative(direction)), direction.getOpposite()); } private boolean isSideCovered(BlockEntity blockEntity, Direction direction) { if (blockEntity == null) { return false; } INetworkNode node = blockEntity instanceof INetworkNodeProxy proxy ? proxy.getNode() : null; if (node instanceof ICoverable coverable) { Cover cover = coverable.getCoverManager().getCover(direction); if (cover == null) { return false; } else { return cover.getType() == CoverType.NORMAL; } } return false; } private BlockState getState(BlockState currentState, LevelAccessor level, BlockPos pos) { boolean north = hasNodeConnection(level, pos.relative(Direction.NORTH), currentState, Direction.SOUTH); boolean east = hasNodeConnection(level, pos.relative(Direction.EAST), currentState, Direction.WEST); boolean south = hasNodeConnection(level, pos.relative(Direction.SOUTH), currentState, Direction.NORTH); boolean west = hasNodeConnection(level, pos.relative(Direction.WEST), currentState, Direction.EAST); boolean up = hasNodeConnection(level, pos.relative(Direction.UP), currentState, Direction.DOWN); boolean down = hasNodeConnection(level, pos.relative(Direction.DOWN), currentState, Direction.UP); return currentState .setValue(NORTH, north) .setValue(EAST, east) .setValue(SOUTH, south) .setValue(WEST, west) .setValue(UP, up) .setValue(DOWN, down); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new CableBlockEntity(pos, state); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); builder.add(NORTH, EAST, SOUTH, WEST, UP, DOWN, WATERLOGGED); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ColoredNetworkBlock.java ================================================ package com.refinedmods.refinedstorage.block; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; public abstract class ColoredNetworkBlock extends NetworkNodeBlock { public ColoredNetworkBlock(Properties props) { super(props); } // Don't do block drops if we change the color. @Override public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { if (state.getBlock().getClass().equals(newState.getBlock().getClass())) { checkIfDirectionHasChanged(state, level, pos, newState); } else { super.onRemove(state, level, pos, newState, isMoving); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ConstructorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.container.ConstructorContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.CollisionUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class ConstructorBlock extends CableBlock { private static final VoxelShape HEAD_NORTH = Shapes.or(box(2, 2, 0, 14, 14, 2), HOLDER_NORTH); private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 2, 2, 16, 14, 14), HOLDER_EAST); private static final VoxelShape HEAD_SOUTH = Shapes.or(box(2, 2, 14, 14, 14, 16), HOLDER_SOUTH); private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 2, 2, 2, 14, 14), HOLDER_WEST); private static final VoxelShape HEAD_DOWN = Shapes.or(box(2, 0, 2, 14, 2, 14), HOLDER_DOWN); private static final VoxelShape HEAD_UP = Shapes.or(box(2, 14, 2, 14, 16, 14), HOLDER_UP); public ConstructorBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new ConstructorBlockEntity(pos, state); } @Override public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> { VoxelShape shape = getCableShape(s); shape = Shapes.or(shape, getHeadShape(s)); return shape; }), world, pos); } private VoxelShape getHeadShape(BlockState state) { Direction direction = state.getValue(getDirection().getProperty()); if (direction == Direction.NORTH) { return HEAD_NORTH; } if (direction == Direction.EAST) { return HEAD_EAST; } if (direction == Direction.SOUTH) { return HEAD_SOUTH; } if (direction == Direction.WEST) { return HEAD_WEST; } if (direction == Direction.UP) { return HEAD_UP; } if (direction == Direction.DOWN) { return HEAD_DOWN; } return Shapes.empty(); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.constructor"), (blockEntity, windowId, inventory, p) -> new ConstructorContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ControllerBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.Network; import com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity; import com.refinedmods.refinedstorage.container.ControllerContainerMenu; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.ColorMap; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.util.StringRepresentable; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.BlockHitResult; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; import javax.annotation.Nullable; public class ControllerBlock extends BaseBlock implements EntityBlock { public static final EnumProperty ENERGY_TYPE = EnumProperty.create("energy_type", EnergyType.class); private final NetworkType type; public ControllerBlock(NetworkType type) { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.type = type; this.registerDefaultState(getStateDefinition().any().setValue(ENERGY_TYPE, EnergyType.OFF)); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); builder.add(ENERGY_TYPE); } public NetworkType getType() { return type; } @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) { super.setPlacedBy(level, pos, state, entity, stack); if (!level.isClientSide) { IEnergyStorage energyFromStack = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyFromStack != null) { IEnergyStorage energyFromBlockEntity = level.getCapability(Capabilities.EnergyStorage.BLOCK, pos, Direction.NORTH); if (energyFromBlockEntity != null) { energyFromBlockEntity.receiveEnergy(energyFromStack.getEnergyStored(), false); } } } } @Override @SuppressWarnings("deprecation") public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving); if (!level.isClientSide) { INetwork network = API.instance().getNetworkManager((ServerLevel) level).getNetwork(pos); if (network instanceof Network) { ((Network) network).setRedstonePowered(level.hasNeighborSignal(pos)); } } } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = super.use(state, level, pos, player, hand, hit); if (result != InteractionResult.PASS) { return result; } ColorMap colorMap = type == NetworkType.CREATIVE ? RSBlocks.CREATIVE_CONTROLLER : RSBlocks.CONTROLLER; DyeColor color = DyeColor.getColor(player.getItemInHand(hand)); if (color != null && !state.getBlock().equals(colorMap.get(color).get())) { BlockState newState = colorMap.get(color).get().defaultBlockState().setValue(ENERGY_TYPE, state.getValue(ENERGY_TYPE)); return RSBlocks.CONTROLLER.setBlockState(newState, player.getItemInHand(hand), level, pos, player); } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new MenuProvider() { @Override public Component getDisplayName() { return Component.translatable("gui.refinedstorage." + (ControllerBlock.this.getType() == NetworkType.CREATIVE ? "creative_" : "") + "controller"); } @Override public AbstractContainerMenu createMenu(int i, Inventory playerInventory, Player player) { return new ControllerContainerMenu((ControllerBlockEntity) level.getBlockEntity(pos), player, i); } }, pos )); } return InteractionResult.SUCCESS; } @Override public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { if (newState.getBlock() instanceof ControllerBlock) { return; } super.onRemove(state, level, pos, newState, isMoving); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new ControllerBlockEntity(type, pos, state); } public enum EnergyType implements StringRepresentable { OFF("off"), NEARLY_OFF("nearly_off"), NEARLY_ON("nearly_on"), ON("on"); private final String name; EnergyType(String name) { this.name = name; } @Override public String getSerializedName() { return name; } @Override public String toString() { return name; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/CrafterBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.CrafterContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import javax.annotation.Nullable; public class CrafterBlock extends ColoredNetworkBlock { public CrafterBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY_FACE_PLAYER; } @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { super.setPlacedBy(level, pos, state, placer, stack); if (!level.isClientSide) { BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof CrafterBlockEntity && stack.hasCustomHoverName()) { ((CrafterBlockEntity) blockEntity).getNode().setDisplayName(stack.getHoverName()); ((CrafterBlockEntity) blockEntity).getNode().markDirty(); } } } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.CRAFTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attempt(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( ((CrafterBlockEntity) level.getBlockEntity(pos)).getNode().getName(), (blockEntity, windowId, inventory, p) -> new CrafterContainerMenu(blockEntity, player, windowId), pos ), pos ), Permission.MODIFY, Permission.AUTOCRAFTING); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new CrafterBlockEntity(pos, state); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/CrafterManagerBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.factory.CrafterManagerMenuProvider; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class CrafterManagerBlock extends ColoredNetworkBlock { public CrafterManagerBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new CrafterManagerBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.CRAFTER_MANAGER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attempt(level, pos, player, () -> player.openMenu( new CrafterManagerMenuProvider((CrafterManagerBlockEntity) level.getBlockEntity(pos)), buf -> CrafterManagerMenuProvider.writeToBuffer(buf, level, pos) ), Permission.MODIFY, Permission.AUTOCRAFTING); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/CraftingMonitorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.factory.CraftingMonitorMenuProvider; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class CraftingMonitorBlock extends ColoredNetworkBlock { public CraftingMonitorBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new CraftingMonitorBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.CRAFTING_MONITOR.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { CraftingMonitorBlockEntity blockEntity = (CraftingMonitorBlockEntity) level.getBlockEntity(pos); return NetworkUtils.attempt(level, pos, player, () -> player.openMenu( new CraftingMonitorMenuProvider(RSContainerMenus.CRAFTING_MONITOR.get(), blockEntity.getNode(), blockEntity), pos ), Permission.MODIFY, Permission.AUTOCRAFTING); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/DestructorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.container.DestructorContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.CollisionUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class DestructorBlock extends CableBlock { private static final VoxelShape HEAD_NORTH = Shapes.or(box(2, 2, 0, 14, 14, 2), HOLDER_NORTH); private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 2, 2, 16, 14, 14), HOLDER_EAST); private static final VoxelShape HEAD_SOUTH = Shapes.or(box(2, 2, 14, 14, 14, 16), HOLDER_SOUTH); private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 2, 2, 2, 14, 14), HOLDER_WEST); private static final VoxelShape HEAD_DOWN = Shapes.or(box(2, 0, 2, 14, 2, 14), HOLDER_DOWN); private static final VoxelShape HEAD_UP = Shapes.or(box(2, 14, 2, 14, 16, 14), HOLDER_UP); public DestructorBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new DestructorBlockEntity(pos, state); } @Override public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> { VoxelShape shape = getCableShape(s); shape = Shapes.or(shape, getHeadShape(s)); return shape; }), world, pos); } private VoxelShape getHeadShape(BlockState state) { Direction direction = state.getValue(getDirection().getProperty()); if (direction == Direction.NORTH) { return HEAD_NORTH; } if (direction == Direction.EAST) { return HEAD_EAST; } if (direction == Direction.SOUTH) { return HEAD_SOUTH; } if (direction == Direction.WEST) { return HEAD_WEST; } if (direction == Direction.UP) { return HEAD_UP; } if (direction == Direction.DOWN) { return HEAD_DOWN; } return Shapes.empty(); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.destructor"), (blockEntity, windowId, inventory, p) -> new DestructorContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/DetectorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.container.DetectorContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.ColorMap; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class DetectorBlock extends ColoredNetworkBlock { public static final BooleanProperty POWERED = BooleanProperty.create("powered"); private static final VoxelShape SHAPE = box(0, 0, 0, 16, 5, 16); public DetectorBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.registerDefaultState(this.getStateDefinition().any().setValue(POWERED, false)); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); builder.add(POWERED); } @Override @SuppressWarnings("deprecation") public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return SHAPE; } @Override @SuppressWarnings("deprecation") public boolean isSignalSource(BlockState state) { return true; } @Override @SuppressWarnings("deprecation") public int getSignal(BlockState state, BlockGetter world, BlockPos pos, Direction side) { BlockEntity blockEntity = world.getBlockEntity(pos); return (blockEntity instanceof DetectorBlockEntity && ((DetectorBlockEntity) blockEntity).getNode().isPowered()) ? 15 : 0; } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { ColorMap colorMap = RSBlocks.DETECTOR; DyeColor color = DyeColor.getColor(player.getItemInHand(hand)); if (color != null && !state.getBlock().equals(colorMap.get(color).get())) { BlockState newState = colorMap.get(color).get().defaultBlockState().setValue(POWERED, state.getValue(POWERED)); return RSBlocks.DETECTOR.setBlockState(newState, player.getItemInHand(hand), level, pos, player); } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.detector"), (blockEntity, windowId, inventory, p) -> new DetectorContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new DetectorBlockEntity(pos, state); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/DiskDriveBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.container.DiskDriveContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class DiskDriveBlock extends NetworkNodeBlock { public DiskDriveBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new DiskDriveBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult rayTraceResult) { if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.disk_drive"), (blockEntity, windowId, inventory, p) -> new DiskDriveContainerMenu(blockEntity, p, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/DiskManipulatorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class DiskManipulatorBlock extends ColoredNetworkBlock { public DiskManipulatorBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new DiskManipulatorBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult rayTraceResult) { InteractionResult result = RSBlocks.DISK_MANIPULATOR.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.disk_manipulator"), (blockEntity, windowId, inventory, p) -> new DiskManipulatorContainerMenu(blockEntity, p, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ExporterBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.container.ExporterContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.CollisionUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class ExporterBlock extends CableBlock { private static final VoxelShape LINE_NORTH_1 = box(6, 6, 0, 10, 10, 2); private static final VoxelShape LINE_NORTH_2 = box(5, 5, 2, 11, 11, 4); private static final VoxelShape LINE_NORTH_3 = box(3, 3, 4, 13, 13, 6); private static final VoxelShape LINE_NORTH = Shapes.or(LINE_NORTH_1, LINE_NORTH_2, LINE_NORTH_3); private static final VoxelShape LINE_EAST_1 = box(14, 6, 6, 16, 10, 10); private static final VoxelShape LINE_EAST_2 = box(12, 5, 5, 14, 11, 11); private static final VoxelShape LINE_EAST_3 = box(10, 3, 3, 12, 13, 13); private static final VoxelShape LINE_EAST = Shapes.or(LINE_EAST_1, LINE_EAST_2, LINE_EAST_3); private static final VoxelShape LINE_SOUTH_1 = box(6, 6, 14, 10, 10, 16); private static final VoxelShape LINE_SOUTH_2 = box(5, 5, 12, 11, 11, 14); private static final VoxelShape LINE_SOUTH_3 = box(3, 3, 10, 13, 13, 12); private static final VoxelShape LINE_SOUTH = Shapes.or(LINE_SOUTH_1, LINE_SOUTH_2, LINE_SOUTH_3); private static final VoxelShape LINE_WEST_1 = box(0, 6, 6, 2, 10, 10); private static final VoxelShape LINE_WEST_2 = box(2, 5, 5, 4, 11, 11); private static final VoxelShape LINE_WEST_3 = box(4, 3, 3, 6, 13, 13); private static final VoxelShape LINE_WEST = Shapes.or(LINE_WEST_1, LINE_WEST_2, LINE_WEST_3); private static final VoxelShape LINE_UP_1 = box(6, 14, 6, 10, 16, 10); private static final VoxelShape LINE_UP_2 = box(5, 12, 5, 11, 14, 11); private static final VoxelShape LINE_UP_3 = box(3, 10, 3, 13, 12, 13); private static final VoxelShape LINE_UP = Shapes.or(LINE_UP_1, LINE_UP_2, LINE_UP_3); private static final VoxelShape LINE_DOWN_1 = box(6, 0, 6, 10, 2, 10); private static final VoxelShape LINE_DOWN_2 = box(5, 2, 5, 11, 4, 11); private static final VoxelShape LINE_DOWN_3 = box(3, 4, 3, 13, 6, 13); private static final VoxelShape LINE_DOWN = Shapes.or(LINE_DOWN_1, LINE_DOWN_2, LINE_DOWN_3); public ExporterBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> { VoxelShape shape = getCableShape(s); shape = Shapes.or(shape, getLineShape(s)); return shape; }), world, pos); } private VoxelShape getLineShape(BlockState state) { Direction direction = state.getValue(getDirection().getProperty()); if (direction == Direction.NORTH) { return LINE_NORTH; } if (direction == Direction.EAST) { return LINE_EAST; } if (direction == Direction.SOUTH) { return LINE_SOUTH; } if (direction == Direction.WEST) { return LINE_WEST; } if (direction == Direction.UP) { return LINE_UP; } if (direction == Direction.DOWN) { return LINE_DOWN; } return Shapes.empty(); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new ExporterBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide && CollisionUtils.isInBounds(getLineShape(state), pos, hit.getLocation())) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.exporter"), (blockEntity, windowId, inventory, p) -> new ExporterContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ExternalStorageBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.container.ExternalStorageContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.CollisionUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class ExternalStorageBlock extends CableBlock { private static final VoxelShape HEAD_NORTH = Shapes.or(box(3, 3, 0, 13, 13, 2), HOLDER_NORTH); private static final VoxelShape HEAD_EAST = Shapes.or(box(14, 3, 3, 16, 13, 13), HOLDER_EAST); private static final VoxelShape HEAD_SOUTH = Shapes.or(box(3, 3, 14, 13, 13, 16), HOLDER_SOUTH); private static final VoxelShape HEAD_WEST = Shapes.or(box(0, 3, 3, 2, 13, 13), HOLDER_WEST); private static final VoxelShape HEAD_UP = Shapes.or(box(3, 14, 3, 13, 16, 13), HOLDER_UP); private static final VoxelShape HEAD_DOWN = Shapes.or(box(3, 0, 3, 13, 2, 13), HOLDER_DOWN); public ExternalStorageBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> { VoxelShape shape = getCableShape(s); shape = Shapes.or(shape, getHeadShape(s)); return shape; }), world, pos); } private VoxelShape getHeadShape(BlockState state) { Direction direction = state.getValue(getDirection().getProperty()); if (direction == Direction.NORTH) { return HEAD_NORTH; } if (direction == Direction.EAST) { return HEAD_EAST; } if (direction == Direction.SOUTH) { return HEAD_SOUTH; } if (direction == Direction.WEST) { return HEAD_WEST; } if (direction == Direction.UP) { return HEAD_UP; } if (direction == Direction.DOWN) { return HEAD_DOWN; } return Shapes.empty(); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new ExternalStorageBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide && CollisionUtils.isInBounds(getHeadShape(state), pos, hit.getLocation())) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.external_storage"), (blockEntity, windowId, inventory, p) -> new ExternalStorageContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override @SuppressWarnings("deprecation") public void neighborChanged(BlockState state, Level level, BlockPos pos, Block block, BlockPos fromPos, boolean isMoving) { super.neighborChanged(state, level, pos, block, fromPos, isMoving); if (!level.isClientSide) { INetworkNode node = NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(pos)); if (node instanceof ExternalStorageNetworkNode && node.getNetwork() != null && fromPos.equals(pos.relative(((ExternalStorageNetworkNode) node).getDirection()))) { ((ExternalStorageNetworkNode) node).updateStorage(node.getNetwork(), InvalidateCause.NEIGHBOR_CHANGED); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/FluidInterfaceBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.FluidInterfaceContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class FluidInterfaceBlock extends NetworkNodeBlock { public FluidInterfaceBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new FluidInterfaceBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide) { return NetworkUtils.attempt(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.fluid_interface"), (blockEntity, windowId, inventory, p) -> new FluidInterfaceContainerMenu(blockEntity, player, windowId), pos ), pos ), Permission.MODIFY, Permission.INSERT, Permission.EXTRACT); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/FluidStorageBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.container.FluidStorageContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class FluidStorageBlock extends NetworkNodeBlock { private final FluidStorageType type; public FluidStorageBlock(FluidStorageType type) { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.type = type; } public FluidStorageType getType() { return type; } @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, LivingEntity player, ItemStack stack) { if (!level.isClientSide) { FluidStorageNetworkNode storage = ((FluidStorageBlockEntity) level.getBlockEntity(pos)).getNode(); if (stack.hasTag() && stack.getTag().hasUUID(FluidStorageNetworkNode.NBT_ID)) { storage.setStorageId(stack.getTag().getUUID(FluidStorageNetworkNode.NBT_ID)); } storage.loadStorage(player instanceof Player ? (Player) player : null); } // Call this after loading the storage, so the network discovery can use the loaded storage. super.setPlacedBy(level, pos, state, player, stack); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new FluidStorageBlockEntity(type, pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( ((FluidStorageBlockEntity) level.getBlockEntity(pos)).getNode().getTitle(), (blockEntity, windowId, inventory, p) -> new FluidStorageContainerMenu(blockEntity, player, windowId), pos ), pos)); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/GridBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.GridBlockGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.util.BlockColorMap; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.ColorMap; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.client.color.block.BlockColor; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class GridBlock extends ColoredNetworkBlock { private final GridType type; public GridBlock(GridType type) { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.type = type; } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public boolean hasConnectedState() { return true; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new GridBlockEntity(type, pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { BlockColorMap map; switch (type) { case FLUID: map = RSBlocks.FLUID_GRID; break; case NORMAL: map = RSBlocks.GRID; break; case CRAFTING: map = RSBlocks.CRAFTING_GRID; break; case PATTERN: map = RSBlocks.PATTERN_GRID; break; default: throw new IllegalStateException("Unexpected value: " + type); } InteractionResult result = map.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> API.instance().getGridManager().openGrid(GridBlockGridFactory.ID, (ServerPlayer) player, pos)); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/ImporterBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.block.shape.ShapeCache; import com.refinedmods.refinedstorage.container.ImporterContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.CollisionUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class ImporterBlock extends CableBlock { private static final VoxelShape LINE_NORTH_1 = box(6, 6, 4, 10, 10, 6); private static final VoxelShape LINE_NORTH_2 = box(5, 5, 2, 11, 11, 4); private static final VoxelShape LINE_NORTH_3 = box(3, 3, 0, 13, 13, 2); private static final VoxelShape LINE_NORTH = Shapes.or(LINE_NORTH_1, LINE_NORTH_2, LINE_NORTH_3); private static final VoxelShape LINE_EAST_1 = box(10, 6, 6, 12, 10, 10); private static final VoxelShape LINE_EAST_2 = box(12, 5, 5, 14, 11, 11); private static final VoxelShape LINE_EAST_3 = box(14, 3, 3, 16, 13, 13); private static final VoxelShape LINE_EAST = Shapes.or(LINE_EAST_1, LINE_EAST_2, LINE_EAST_3); private static final VoxelShape LINE_SOUTH_1 = box(6, 6, 10, 10, 10, 12); private static final VoxelShape LINE_SOUTH_2 = box(5, 5, 12, 11, 11, 14); private static final VoxelShape LINE_SOUTH_3 = box(3, 3, 14, 13, 13, 16); private static final VoxelShape LINE_SOUTH = Shapes.or(LINE_SOUTH_1, LINE_SOUTH_2, LINE_SOUTH_3); private static final VoxelShape LINE_WEST_1 = box(4, 6, 6, 6, 10, 10); private static final VoxelShape LINE_WEST_2 = box(2, 5, 5, 4, 11, 11); private static final VoxelShape LINE_WEST_3 = box(0, 3, 3, 2, 13, 13); private static final VoxelShape LINE_WEST = Shapes.or(LINE_WEST_1, LINE_WEST_2, LINE_WEST_3); private static final VoxelShape LINE_UP_1 = box(6, 10, 6, 10, 12, 10); private static final VoxelShape LINE_UP_2 = box(5, 12, 5, 11, 14, 11); private static final VoxelShape LINE_UP_3 = box(3, 14, 3, 13, 16, 13); private static final VoxelShape LINE_UP = Shapes.or(LINE_UP_1, LINE_UP_2, LINE_UP_3); private static final VoxelShape LINE_DOWN_1 = box(6, 4, 6, 10, 6, 10); private static final VoxelShape LINE_DOWN_2 = box(5, 2, 5, 11, 4, 11); private static final VoxelShape LINE_DOWN_3 = box(3, 0, 3, 13, 2, 13); private static final VoxelShape LINE_DOWN = Shapes.or(LINE_DOWN_1, LINE_DOWN_2, LINE_DOWN_3); public ImporterBlock() { super(BlockUtils.DEFAULT_GLASS_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext ctx) { return ConstantsCable.addCoverVoxelShapes(ShapeCache.getOrCreate(state, s -> { VoxelShape shape = getCableShape(s); shape = Shapes.or(shape, getLineShape(s)); return shape; }), world, pos); } private VoxelShape getLineShape(BlockState state) { Direction direction = state.getValue(getDirection().getProperty()); if (direction == Direction.NORTH) { return LINE_NORTH; } if (direction == Direction.EAST) { return LINE_EAST; } if (direction == Direction.SOUTH) { return LINE_SOUTH; } if (direction == Direction.WEST) { return LINE_WEST; } if (direction == Direction.UP) { return LINE_UP; } if (direction == Direction.DOWN) { return LINE_DOWN; } return Shapes.empty(); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new ImporterBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide && CollisionUtils.isInBounds(getLineShape(state), pos, hit.getLocation())) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.importer"), (blockEntity, windowId, inventory, p) -> new ImporterContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/InterfaceBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.InterfaceContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class InterfaceBlock extends NetworkNodeBlock { public InterfaceBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new InterfaceBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide) { return NetworkUtils.attempt(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.interface"), (blockEntity, windowId, inventory, p) -> new InterfaceContainerMenu(blockEntity, player, windowId), pos ), pos ), Permission.MODIFY, Permission.INSERT, Permission.EXTRACT); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/MachineCasingBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.util.BlockUtils; public class MachineCasingBlock extends BaseBlock { public MachineCasingBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/NetworkNodeBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.NonNullList; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.neoforged.neoforge.items.IItemHandler; public abstract class NetworkNodeBlock extends BaseBlock implements EntityBlock { public static final BooleanProperty CONNECTED = BooleanProperty.create("connected"); protected NetworkNodeBlock(BlockBehaviour.Properties props) { super(props); if (hasConnectedState()) { this.registerDefaultState(this.getStateDefinition().any().setValue(CONNECTED, false)); } } @Override @SuppressWarnings("deprecation") public void neighborChanged(BlockState state, Level level, BlockPos pos, Block blockIn, BlockPos fromPos, boolean isMoving) { super.neighborChanged(state, level, pos, blockIn, fromPos, isMoving); if (!level.isClientSide) { INetworkNode node = API.instance().getNetworkNodeManager((ServerLevel) level).getNode(pos); if (node instanceof NetworkNode) { ((NetworkNode) node).setRedstonePowered(level.hasNeighborSignal(pos)); } } } @Override public void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) { if (state.getBlock() != newState.getBlock()) { BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof NetworkNodeBlockEntity) { IItemHandler handler = ((NetworkNodeBlockEntity) blockEntity).getNode().getDrops(); if (handler != null) { NonNullList drops = NonNullList.create(); for (int i = 0; i < handler.getSlots(); ++i) { drops.add(handler.getStackInSlot(i)); } Containers.dropContents(level, pos, drops); } } } // Call onReplaced after the drops check so the tile still exists super.onRemove(state, level, pos, newState, isMoving); } @Override protected void onDirectionChanged(Level level, BlockPos pos, Direction newDirection) { super.onDirectionChanged(level, pos, newDirection); BlockEntity blockEntity = level.getBlockEntity(pos); if (blockEntity instanceof INetworkNodeProxy) { INetworkNode node = ((INetworkNodeProxy) blockEntity).getNode(); if (node instanceof NetworkNode) { ((NetworkNode) node).onDirectionChanged(newDirection); } } } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); if (hasConnectedState()) { builder.add(CONNECTED); } } public boolean hasConnectedState() { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/NetworkReceiverBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.blockentity.NetworkReceiverBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class NetworkReceiverBlock extends ColoredNetworkBlock { public NetworkReceiverBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new NetworkReceiverBlockEntity(pos, state); } @Override public boolean hasConnectedState() { return true; } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { return RSBlocks.NETWORK_RECEIVER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/NetworkTransmitterBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity; import com.refinedmods.refinedstorage.container.NetworkTransmitterContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class NetworkTransmitterBlock extends ColoredNetworkBlock { public NetworkTransmitterBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new NetworkTransmitterBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.NETWORK_TRANSMITTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.network_transmitter"), (blockEntity, windowId, inventory, p) -> new NetworkTransmitterContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/PortableGridBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridBlockGridFactory; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridDiskState; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import com.refinedmods.refinedstorage.util.BlockUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.EntityBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityTicker; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import javax.annotation.Nullable; public class PortableGridBlock extends BaseBlock implements EntityBlock { public static final EnumProperty DISK_STATE = EnumProperty.create("disk_state", PortableGridDiskState.class); public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); private static final VoxelShape SHAPE = box(0, 0, 0, 16, 13.2, 16); private final PortableGridBlockItem.Type type; public PortableGridBlock(PortableGridBlockItem.Type type) { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.type = type; this.registerDefaultState(defaultBlockState().setValue(DISK_STATE, PortableGridDiskState.NONE).setValue(ACTIVE, false)); } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { super.createBlockStateDefinition(builder); builder.add(DISK_STATE); builder.add(ACTIVE); } @Override @SuppressWarnings("deprecation") public VoxelShape getShape(BlockState state, BlockGetter worldIn, BlockPos pos, CollisionContext context) { return SHAPE; } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new PortableGridBlockEntity(type, pos, state); } @Override public BlockEntityTicker getTicker(Level level, BlockState state, BlockEntityType type) { return level.isClientSide ? null : new BlockEntityTicker() { @Override public void tick(Level level, BlockPos pos, BlockState state, T blockEntity) { if (blockEntity instanceof PortableGridBlockEntity) { PortableGridBlockEntity.serverTick((PortableGridBlockEntity) blockEntity); } } }; } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { if (!level.isClientSide) { API.instance().getGridManager().openGrid(PortableGridBlockGridFactory.ID, (ServerPlayer) player, pos); ((PortableGridBlockEntity) level.getBlockEntity(pos)).onOpened(); } return InteractionResult.SUCCESS; } @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) { super.setPlacedBy(level, pos, state, placer, stack); if (!level.isClientSide) { ((PortableGridBlockEntity) level.getBlockEntity(pos)).applyDataFromItemToBlockEntity(stack); ((PortableGridBlockEntity) level.getBlockEntity(pos)).updateState(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/QuartzEnrichedIronBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.util.BlockUtils; public class QuartzEnrichedIronBlock extends BaseBlock { public QuartzEnrichedIronBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/RelayBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.container.RelayContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.RelayBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class RelayBlock extends ColoredNetworkBlock { public RelayBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new RelayBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.RELAY.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.relay"), (blockEntity, windowId, inventory, p) -> new RelayContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/SecurityManagerBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; public class SecurityManagerBlock extends ColoredNetworkBlock { public SecurityManagerBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.SECURITY_MANAGER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { Runnable action = () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.security_manager"), (blockEntity, windowId, inventory, p) -> new SecurityManagerContainerMenu(blockEntity, player, windowId), pos ), pos ); if (player.getGameProfile().getId().equals(((SecurityManagerBlockEntity) level.getBlockEntity(pos)).getNode().getOwner())) { action.run(); } else { return NetworkUtils.attempt(level, pos, player, action, Permission.MODIFY, Permission.SECURITY); } } return InteractionResult.SUCCESS; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new SecurityManagerBlockEntity(pos, state); } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/StorageBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.container.StorageContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.StorageBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import javax.annotation.Nullable; public class StorageBlock extends NetworkNodeBlock { private final ItemStorageType type; public StorageBlock(ItemStorageType type) { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); this.type = type; } public ItemStorageType getType() { return type; } @Override public void setPlacedBy(Level level, BlockPos pos, BlockState state, @Nullable LivingEntity entity, ItemStack stack) { if (!level.isClientSide) { StorageNetworkNode storage = ((StorageBlockEntity) level.getBlockEntity(pos)).getNode(); if (stack.hasTag() && stack.getTag().hasUUID(StorageNetworkNode.NBT_ID)) { storage.setStorageId(stack.getTag().getUUID(StorageNetworkNode.NBT_ID)); } storage.loadStorage(entity instanceof Player ? (Player) entity : null); } // Call this after loading the storage, so the network discovery can use the loaded storage. super.setPlacedBy(level, pos, state, entity, stack); } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new StorageBlockEntity(type, pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( ((StorageBlockEntity) level.getBlockEntity(pos)).getNode().getTitle(), (blockEntity, windowId, inventory, p) -> new StorageContainerMenu(blockEntity, player, windowId), pos ), pos)); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/StorageMonitorBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode; import com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity; import com.refinedmods.refinedstorage.container.StorageMonitorContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; public class StorageMonitorBlock extends NetworkNodeBlock { public StorageMonitorBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.HORIZONTAL; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new StorageMonitorBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) { if (!level.isClientSide) { ItemStack held = player.getItemInHand(handIn); if (player.isCrouching()) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.storage_monitor"), (blockEntity, windowId, inventory, p) -> new StorageMonitorContainerMenu(blockEntity, player, windowId), pos ), pos )); } else { StorageMonitorNetworkNode storageMonitor = ((StorageMonitorBlockEntity) level.getBlockEntity(pos)).getNode(); if (!held.isEmpty()) { return storageMonitor.deposit(player, held); } else { return storageMonitor.depositAll(player); } } } return InteractionResult.SUCCESS; } @Override @SuppressWarnings("deprecation") public void attack(BlockState state, Level level, BlockPos pos, Player player) { super.attack(state, level, pos, player); if (!level.isClientSide) { HitResult result = LevelUtils.rayTracePlayer(level, player); if (!(result instanceof BlockHitResult)) { return; } ((StorageMonitorBlockEntity) level.getBlockEntity(pos)).getNode().extract(player, ((BlockHitResult) result).getDirection()); } } @Override public boolean hasConnectedState() { return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/WirelessTransmitterBlock.java ================================================ package com.refinedmods.refinedstorage.block; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.container.WirelessTransmitterContainerMenu; import com.refinedmods.refinedstorage.container.factory.BlockEntityMenuProvider; import com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity; import com.refinedmods.refinedstorage.util.BlockUtils; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class WirelessTransmitterBlock extends ColoredNetworkBlock { private static final VoxelShape SHAPE_DOWN = box(6.0D, 0.0D, 6.0D, 10.0D, 10.0D, 10.0D); private static final VoxelShape SHAPE_UP = box(6.0D, 6.0D, 6.0D, 10.0D, 16.0D, 10.0D); private static final VoxelShape SHAPE_EAST = box(6.0D, 6.0D, 6.0D, 16.0D, 10.0D, 10.0D); private static final VoxelShape SHAPE_WEST = box(0.0D, 6.0D, 6.0D, 10.0D, 10.0D, 10.0D); private static final VoxelShape SHAPE_NORTH = box(6.0D, 6.0D, 0.0D, 10.0D, 10.0D, 10.0D); private static final VoxelShape SHAPE_SOUTH = box(6.0D, 6.0D, 6.0D, 10.0D, 10.0D, 16.0D); public WirelessTransmitterBlock() { super(BlockUtils.DEFAULT_ROCK_PROPERTIES); } @Override public BlockDirection getDirection() { return BlockDirection.ANY; } @Override public boolean hasConnectedState() { return true; } @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new WirelessTransmitterBlockEntity(pos, state); } @Override @SuppressWarnings("deprecation") public VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) { switch (state.getValue(getDirection().getProperty())) { case DOWN: return SHAPE_DOWN; case UP: return SHAPE_UP; case NORTH: return SHAPE_NORTH; case SOUTH: return SHAPE_SOUTH; case WEST: return SHAPE_WEST; case EAST: return SHAPE_EAST; default: return Shapes.empty(); } } @Override @SuppressWarnings("deprecation") public InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { InteractionResult result = RSBlocks.WIRELESS_TRANSMITTER.changeBlockColor(state, player.getItemInHand(hand), level, pos, player); if (result != InteractionResult.PASS) { return result; } if (!level.isClientSide) { return NetworkUtils.attemptModify(level, pos, player, () -> player.openMenu( new BlockEntityMenuProvider( Component.translatable("gui.refinedstorage.wireless_transmitter"), (blockEntity, windowId, inventory, p) -> new WirelessTransmitterContainerMenu(blockEntity, player, windowId), pos ), pos )); } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/block/shape/ShapeCache.java ================================================ package com.refinedmods.refinedstorage.block.shape; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.VoxelShape; import java.util.HashMap; import java.util.Map; import java.util.function.Function; public final class ShapeCache { private static final Map CACHE = new HashMap<>(); private ShapeCache() { } public static VoxelShape getOrCreate(BlockState state, Function shapeFactory) { return CACHE.computeIfAbsent(state, shapeFactory); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/BaseBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.Connection; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; public abstract class BaseBlockEntity extends BlockEntity { private final BlockEntitySynchronizationManager dataManager; private boolean unloaded; protected BaseBlockEntity(BlockEntityType type, BlockPos pos, BlockState state, BlockEntitySynchronizationSpec syncSpec) { super(type, pos, state); this.dataManager = new BlockEntitySynchronizationManager(this, syncSpec); } public BlockEntitySynchronizationManager getDataManager() { return dataManager; } public CompoundTag writeUpdate(CompoundTag tag) { return tag; } public void readUpdate(CompoundTag tag) { } @Override public final CompoundTag getUpdateTag() { return writeUpdate(super.getUpdateTag()); } @Override public final ClientboundBlockEntityDataPacket getUpdatePacket() { return ClientboundBlockEntityDataPacket.create(this, BlockEntity::getUpdateTag); } @Override public final void onDataPacket(Connection net, ClientboundBlockEntityDataPacket packet) { readUpdate(packet.getTag()); } @Override public void handleUpdateTag(CompoundTag tag) { super.handleUpdateTag(tag); readUpdate(tag); } @Override public void setRemoved() { super.setRemoved(); // @Volatile: MC calls setRemoved when a chunk unloads now as well (see ServerLevel#unload -> LevelChunk#clearAllBlockEntities). // Since we don't want to remove network node data in that case, we need to know if it was removed due to unloading. // We can use "unloaded" for that, it's set in #onChunkUnloaded. // Since MC first calls #onChunkUnloaded and then #setRemoved, this check keeps working. if (!unloaded) { onRemovedNotDueToChunkUnload(); } } protected void onRemovedNotDueToChunkUnload() { // NO OP } @Override public void onChunkUnloaded() { super.onChunkUnloaded(); unloaded = true; } // @Volatile: Copied with some changes from the super method (avoid sending neighbor updates, it's not needed) @Override public void setChanged() { if (level != null) { level.blockEntityChanged(worldPosition); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/CableBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; public class CableBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter 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) -> { }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COVER_MANAGER) .build(); public CableBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.CABLE.get(), pos, state, SPEC, CableNetworkNode.class); } @Override @Nonnull public CableNetworkNode createNode(Level level, BlockPos pos) { return new CableNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ClientNode.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; public class ClientNode { private final ItemStack stack; private final int energyUsage; private int amount; public ClientNode(ItemStack stack, int amount, int energyUsage) { this.stack = stack; this.amount = amount; this.energyUsage = energyUsage; } public ItemStack getStack() { return stack; } public int getAmount() { return amount; } public void setAmount(int amount) { this.amount = amount; } public int getEnergyUsage() { return energyUsage; } @Override public boolean equals(Object other) { if (this == other) { return true; } if (!(other instanceof ClientNode)) { return false; } return energyUsage == ((ClientNode) other).energyUsage && API.instance().getComparer().isEqual(stack, ((ClientNode) other).stack); } @Override public int hashCode() { int result = stack.hashCode(); result = 31 * result + energyUsage; return result; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ConstructorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.ConstructorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; public class ConstructorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "constructor_compare")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "constructor_type")); public static final BlockEntitySynchronizationParameter DROP = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "constructor_drop"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isDrop(), (t, v) -> { t.getNode().setDrop(v); t.getNode().markDirty(); }); public static final BlockEntitySynchronizationParameter COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "constructor_cover_manager"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> { }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(TYPE) .addWatchedParameter(DROP) .addWatchedParameter(COVER_MANAGER) .build(); public ConstructorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.CONSTRUCTOR.get(), pos, state, SPEC, ConstructorNetworkNode.class); } @Override @Nonnull public ConstructorNetworkNode createNode(Level level, BlockPos pos) { return new ConstructorNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ControllerBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.INetworkManager; import com.refinedmods.refinedstorage.api.network.INetworkNodeGraphEntry; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.Network; import com.refinedmods.refinedstorage.apiimpl.network.node.RootNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import net.minecraft.core.BlockPos; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; public class ControllerBlockEntity extends BaseBlockEntity implements INetworkNodeProxy, IRedstoneConfigurable { private static final Logger LOGGER = LogManager.getLogger(); public static final BlockEntitySynchronizationParameter REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, "controller_redstone_mode")); public static final BlockEntitySynchronizationParameter ENERGY_USAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "controller_energy_usage"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyUsage()); public static final BlockEntitySynchronizationParameter ENERGY_STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "controller_energy_stored"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyStorage().getEnergyStored()); public static final BlockEntitySynchronizationParameter ENERGY_CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "controller_energy_capacity"), EntityDataSerializers.INT, 0, t -> t.getNetwork().getEnergyStorage().getMaxEnergyStored()); public static final BlockEntitySynchronizationParameter, ControllerBlockEntity> NODES = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "controller_nodes"), RSSerializers.CLIENT_NODE_SERIALIZER, new ArrayList<>(), ControllerBlockEntity::collectClientNodes); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(ENERGY_USAGE) .addWatchedParameter(ENERGY_STORED) .addParameter(ENERGY_CAPACITY) .addParameter(NODES) .build(); private final NetworkType type; private INetwork removedNetwork; private Network dummyNetwork; public ControllerBlockEntity(NetworkType type, BlockPos pos, BlockState state) { super(type == NetworkType.CREATIVE ? RSBlockEntities.CREATIVE_CONTROLLER.get() : RSBlockEntities.CONTROLLER.get(), pos, state, SPEC); this.type = type; } private static List collectClientNodes(ControllerBlockEntity blockEntity) { List nodes = new ArrayList<>(); for (INetworkNodeGraphEntry entry : blockEntity.getNetwork().getNodeGraph().all()) { if (entry.getNode().isActive()) { ItemStack stack = entry.getNode().getItemStack(); if (stack.isEmpty()) { continue; } ClientNode clientNode = new ClientNode(stack, 1, entry.getNode().getEnergyUsage()); if (nodes.contains(clientNode)) { ClientNode other = nodes.get(nodes.indexOf(clientNode)); other.setAmount(other.getAmount() + 1); } else { nodes.add(clientNode); } } } nodes.sort((a, b) -> Integer.compare(b.getEnergyUsage(), a.getEnergyUsage())); return nodes; } public INetwork getNetwork() { if (level.isClientSide) { if (dummyNetwork == null) { dummyNetwork = new Network(level, worldPosition, type); } return dummyNetwork; } INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level); INetwork network = manager.getNetwork(worldPosition); if (network == null) { LOGGER.warn("Expected a network @ {} but couldn't find it, creating a new one...", worldPosition); network = new Network(level, worldPosition, type); manager.setNetwork(worldPosition, network); manager.markForSaving(); } return network; } @Override public void clearRemoved() { super.clearRemoved(); if (!level.isClientSide) { INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level); if (manager.getNetwork(worldPosition) == null) { manager.setNetwork(worldPosition, new Network(level, worldPosition, type)); manager.markForSaving(); } } } @Override public void onRemovedNotDueToChunkUnload() { super.onRemovedNotDueToChunkUnload(); if (!level.isClientSide) { INetworkManager manager = API.instance().getNetworkManager((ServerLevel) level); INetwork network = manager.getNetwork(worldPosition); removedNetwork = network; manager.removeNetwork(worldPosition); manager.markForSaving(); network.onRemoved(); } } public INetwork getRemovedNetwork() { return removedNetwork; } @Override @Nonnull public RootNetworkNode getNode() { return ((Network) getNetwork()).getRoot(); } @Override public RedstoneMode getRedstoneMode() { return ((Network) getNetwork()).getRedstoneMode(); } @Override public void setRedstoneMode(RedstoneMode mode) { ((Network) getNetwork()).setRedstoneMode(mode); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/CrafterBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.screen.CrafterBlockEntitySynchronizationClientListener; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.items.IItemHandler; public class CrafterBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafter_mode"), EntityDataSerializers.INT, CrafterNetworkNode.CrafterMode.IGNORE.ordinal(), t -> t.getNode().getMode().ordinal(), (t, v) -> t.getNode().setMode(CrafterNetworkNode.CrafterMode.getById(v))); private static final BlockEntitySynchronizationParameter HAS_ROOT = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafter_has_root"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().getRootContainerNotSelf().isPresent(), null, (t, v) -> new CrafterBlockEntitySynchronizationClientListener().onChanged(t, v)); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(MODE) .addParameter(HAS_ROOT) .build(); public CrafterBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.CRAFTER.get(), pos, state, SPEC, CrafterNetworkNode.class); } @Override @Nonnull public CrafterNetworkNode createNode(Level level, BlockPos pos) { return new CrafterNetworkNode(level, pos); } public IItemHandler getPatterns(@Nullable Direction direction) { if (direction != null && !direction.equals(this.getNode().getDirection())) { return getNode().getPatternInventory(); } return null; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/CrafterManagerBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.CrafterManagerScreen; import net.minecraft.core.BlockPos; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; public class CrafterManagerBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafter_manager_search_box_mode"), EntityDataSerializers.INT, 0, t -> t.getNode().getSearchBoxMode(), (t, v) -> { if (IGrid.isValidSearchBoxMode(v)) { t.getNode().setSearchBoxMode(v); t.getNode().markDirty(); } }, (initial, p) -> BaseScreen.executeLater(CrafterManagerScreen.class, crafterManager -> crafterManager.getSearchField().setMode(p))); public static final BlockEntitySynchronizationParameter SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafter_manager_size"), EntityDataSerializers.INT, IGrid.SIZE_STRETCH, t -> t.getNode().getSize(), (t, v) -> { if (IGrid.isValidSize(v)) { t.getNode().setSize(v); t.getNode().markDirty(); } }, (initial, p) -> BaseScreen.executeLater(CrafterManagerScreen.class, BaseScreen::init)); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(SIZE) .addWatchedParameter(SEARCH_BOX_MODE) .build(); public CrafterManagerBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.CRAFTER_MANAGER.get(), pos, state, SPEC, CrafterManagerNetworkNode.class); } @Override public CrafterManagerNetworkNode createNode(Level level, BlockPos pos) { return new CrafterManagerNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/DestructorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.DestructorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; public class DestructorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "destructor_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "destructor_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "destructor_type")); public static final BlockEntitySynchronizationParameter PICKUP = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "destructor_pickup"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isPickupItem(), (t, v) -> { t.getNode().setPickupItem(v); t.getNode().markDirty(); }); public static final BlockEntitySynchronizationParameter COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "destructor_cover_manager"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> { }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(TYPE) .addWatchedParameter(PICKUP) .addWatchedParameter(COVER_MANAGER) .build(); public DestructorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.DESTRUCTOR.get(), pos, state, SPEC, DestructorNetworkNode.class); } @Override @Nonnull public DestructorNetworkNode createNode(Level level, BlockPos pos) { return new DestructorNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/DetectorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.DetectorScreen; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class DetectorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "detector_compare")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "detector_type")); public static final BlockEntitySynchronizationParameter MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "detector_mode"), EntityDataSerializers.INT, 0, t -> t.getNode().getMode(), (t, v) -> { if (v == DetectorNetworkNode.MODE_UNDER || v == DetectorNetworkNode.MODE_EQUAL || v == DetectorNetworkNode.MODE_ABOVE) { t.getNode().setMode(v); t.getNode().markDirty(); } }); public static final BlockEntitySynchronizationParameter AMOUNT = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "detector_amount"), EntityDataSerializers.INT, 0, t -> t.getNode().getAmount(), (t, v) -> { t.getNode().setAmount(v); t.getNode().markDirty(); }, (initial, value) -> BaseScreen.executeLater(DetectorScreen.class, detectorScreen -> detectorScreen.updateAmountField(value))); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(TYPE) .addWatchedParameter(MODE) .addWatchedParameter(AMOUNT) .build(); private static final String NBT_POWERED = "Powered"; public DetectorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.DETECTOR.get(), pos, state, SPEC, DetectorNetworkNode.class); } @Override public void readUpdate(CompoundTag tag) { getNode().setPowered(tag.getBoolean(NBT_POWERED)); super.readUpdate(tag); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.putBoolean(NBT_POWERED, getNode().isPowered()); return tag; } @Override @Nonnull public DetectorNetworkNode createNode(Level level, BlockPos pos) { return new DetectorNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/DiskDriveBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.*; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import net.neoforged.neoforge.client.model.data.ModelProperty; import javax.annotation.Nonnull; import java.util.Arrays; public class DiskDriveBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, "disk_drive_priority")); public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "disk_drive_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "disk_drive_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "disk_drive_type")); public static final BlockEntitySynchronizationParameter ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, "disk_drive_access_type")); public static final BlockEntitySynchronizationParameter STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "disk_drive_stored"), RSSerializers.LONG_SERIALIZER, 0L, t -> { long stored = 0; for (IStorageDisk storage : t.getNode().getItemDisks()) { if (storage != null) { stored += storage.getStored(); } } for (IStorageDisk storage : t.getNode().getFluidDisks()) { if (storage != null) { stored += storage.getStored(); } } return stored; }); public static final BlockEntitySynchronizationParameter CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "disk_drive_capacity"), RSSerializers.LONG_SERIALIZER, 0L, t -> { long capacity = 0; for (IStorageDisk storage : t.getNode().getItemDisks()) { if (storage != null) { if (storage.getCapacity() == -1) { return -1L; } capacity += storage.getCapacity(); } } for (IStorageDisk storage : t.getNode().getFluidDisks()) { if (storage != null) { if (storage.getCapacity() == -1) { return -1L; } capacity += storage.getCapacity(); } } return capacity; }); public static final ModelProperty DISK_STATE_PROPERTY = new ModelProperty<>(); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(PRIORITY) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(TYPE) .addWatchedParameter(ACCESS_TYPE) .addWatchedParameter(STORED) .addWatchedParameter(CAPACITY) .build(); private static final String NBT_DISK_STATE = "DiskStates"; private final DiskState[] diskState = new DiskState[8]; public DiskDriveBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.DISK_DRIVE.get(), pos, state, SPEC, DiskDriveNetworkNode.class); Arrays.fill(diskState, DiskState.NONE); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); ListTag list = new ListTag(); for (DiskState state : getNode().getDiskState()) { list.add(IntTag.valueOf(state.ordinal())); } tag.put(NBT_DISK_STATE, list); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); ListTag list = tag.getList(NBT_DISK_STATE, Tag.TAG_INT); for (int i = 0; i < list.size(); ++i) { diskState[i] = DiskState.values()[list.getInt(i)]; } requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(DISK_STATE_PROPERTY, diskState).build(); } @Override @Nonnull public DiskDriveNetworkNode createNode(Level level, BlockPos pos) { return new DiskDriveNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/DiskManipulatorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.IntTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import net.neoforged.neoforge.client.model.data.ModelProperty; import javax.annotation.Nonnull; import java.util.Arrays; public class DiskManipulatorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "disk_manipulator_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "disk_manipulator_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "disk_manipulator_type")); public static final BlockEntitySynchronizationParameter IO_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "disk_manipulator_mode"), EntityDataSerializers.INT, DiskManipulatorNetworkNode.IO_MODE_INSERT, t -> t.getNode().getIoMode(), (t, v) -> { t.getNode().setIoMode(v); t.getNode().markDirty(); }); public static final ModelProperty DISK_STATE_PROPERTY = new ModelProperty<>(); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(TYPE) .addWatchedParameter(IO_MODE) .build(); private static final String NBT_DISK_STATE = "DiskStates"; private final DiskState[] diskState = new DiskState[6]; public DiskManipulatorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.DISK_MANIPULATOR.get(), pos, state, SPEC, DiskManipulatorNetworkNode.class); Arrays.fill(diskState, DiskState.NONE); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); ListTag list = new ListTag(); for (DiskState state : getNode().getDiskState()) { list.add(IntTag.valueOf(state.ordinal())); } tag.put(NBT_DISK_STATE, list); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); ListTag list = tag.getList(NBT_DISK_STATE, Tag.TAG_INT); for (int i = 0; i < list.size(); ++i) { diskState[i] = DiskState.values()[list.getInt(i)]; } requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(DISK_STATE_PROPERTY, diskState).build(); } @Override @Nonnull public DiskManipulatorNetworkNode createNode(Level level, BlockPos pos) { return new DiskManipulatorNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ExporterBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.ExporterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; public class ExporterBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COVER_MANAGER = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "exporter_cover_manager"), EntityDataSerializers.COMPOUND_TAG, new CompoundTag(), t -> t.getNode().getCoverManager().writeToNbt(), (t, v) -> t.getNode().getCoverManager().readFromNbt(v), (initial, p) -> { }); public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "exporter_compare")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "exporter_type")); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(TYPE) .addWatchedParameter(COVER_MANAGER) .build(); public ExporterBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.EXPORTER.get(), pos, state, SPEC, ExporterNetworkNode.class); } @Override @Nonnull public ExporterNetworkNode createNode(Level level, BlockPos pos) { return new ExporterNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ExternalStorageBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.externalstorage.IExternalStorage; import com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.config.*; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import com.refinedmods.refinedstorage.config.ServerConfig; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; public class ExternalStorageBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, "external_storage_priority")); public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "external_storage_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "external_storage_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "external_storage_type")); public static final BlockEntitySynchronizationParameter ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, "external_storage_access_type")); public static final BlockEntitySynchronizationParameter STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "external_storage_stored"), RSSerializers.LONG_SERIALIZER, 0L, t -> { long stored = 0; for (IExternalStorage storage : t.getNode().getItemStorages()) { stored += storage.getStored(); } for (IExternalStorage storage : t.getNode().getFluidStorages()) { stored += storage.getStored(); } return stored; }); public static final BlockEntitySynchronizationParameter CAPACITY = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "external_storage_capacity"), RSSerializers.LONG_SERIALIZER, 0L, t -> { long capacity = 0; for (IExternalStorage storage : t.getNode().getItemStorages()) { capacity += storage.getCapacity(); } for (IExternalStorage storage : t.getNode().getFluidStorages()) { capacity += storage.getCapacity(); } return capacity; }); public static final BlockEntitySynchronizationParameter 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) -> { }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(PRIORITY) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(STORED) .addWatchedParameter(CAPACITY) .addWatchedParameter(TYPE) .addWatchedParameter(ACCESS_TYPE) .addWatchedParameter(COVER_MANAGER) .build(); public ExternalStorageBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.EXTERNAL_STORAGE.get(), pos, state, SPEC, ExternalStorageNetworkNode.class); } @Override @Nonnull public ExternalStorageNetworkNode createNode(Level level, BlockPos pos) { return new ExternalStorageNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/FluidInterfaceBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; public class FluidInterfaceBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter TANK_IN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "fluid_interface_in"), RSSerializers.FLUID_STACK_SERIALIZER, FluidStack.EMPTY, t -> t.getNode().getTankIn().getFluid()); public static final BlockEntitySynchronizationParameter TANK_OUT = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "fluid_interface_out"), RSSerializers.FLUID_STACK_SERIALIZER, FluidStack.EMPTY, t -> t.getNode().getTankOut().getFluid()); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addParameter(TANK_IN) .addParameter(TANK_OUT) .build(); public FluidInterfaceBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.FLUID_INTERFACE.get(), pos, state, SPEC, FluidInterfaceNetworkNode.class); } @Override @Nonnull public FluidInterfaceNetworkNode createNode(Level level, BlockPos pos) { return new FluidInterfaceNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/FluidStorageBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.blockentity.config.IAccessType; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IPrioritizable; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class FluidStorageBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, "fluid_storage_priority")); public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "fluid_storage_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "fluid_storage_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, "fluid_storage_access_type")); public static final BlockEntitySynchronizationParameter 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); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(PRIORITY) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(STORED) .addWatchedParameter(ACCESS_TYPE) .build(); private final FluidStorageType type; public FluidStorageBlockEntity(FluidStorageType type, BlockPos pos, BlockState state) { super(getType(type), pos, state, SPEC, FluidStorageNetworkNode.class); this.type = type; } public static BlockEntityType getType(FluidStorageType type) { return switch (type) { case SIXTY_FOUR_K -> RSBlockEntities.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK.get(); case TWO_HUNDRED_FIFTY_SIX_K -> RSBlockEntities.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK.get(); case THOUSAND_TWENTY_FOUR_K -> RSBlockEntities.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK.get(); case FOUR_THOUSAND_NINETY_SIX_K -> RSBlockEntities.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK.get(); case CREATIVE -> RSBlockEntities.CREATIVE_FLUID_STORAGE_BLOCK.get(); }; } public FluidStorageType getFluidStorageType() { return type; } @Override @Nonnull public FluidStorageNetworkNode createNode(Level level, BlockPos pos) { return new FluidStorageNetworkNode(level, pos, type); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/ImporterBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.ImporterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; public class ImporterBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "importer_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "importer_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "importer_type")); public static final BlockEntitySynchronizationParameter 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) -> { }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(TYPE) .addWatchedParameter(COVER_MANAGER) .build(); public ImporterBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.IMPORTER.get(), pos, state, SPEC, ImporterNetworkNode.class); } @Override @Nonnull public ImporterNetworkNode createNode(Level level, BlockPos pos) { return new ImporterNetworkNode(level, pos); } @Nonnull @Override public ModelData getModelData() { return ModelData.builder().with(CoverManager.PROPERTY, this.getNode().getCoverManager()).build(); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); tag.put(CoverManager.NBT_COVER_MANAGER, this.getNode().getCoverManager().writeToNbt()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); this.getNode().getCoverManager().readFromNbt(tag.getCompound(CoverManager.NBT_COVER_MANAGER)); requestModelDataUpdate(); LevelUtils.updateBlock(level, worldPosition); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/InterfaceBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.InterfaceNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class InterfaceBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "interface_compare")); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .build(); public InterfaceBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.INTERFACE.get(), pos, state, SPEC, InterfaceNetworkNode.class); } @Override @Nonnull public InterfaceNetworkNode createNode(Level level, BlockPos pos) { return new InterfaceNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkNodeBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeManager; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nonnull; import javax.annotation.Nullable; public abstract class NetworkNodeBlockEntity extends BaseBlockEntity implements INetworkNodeProxy, IRedstoneConfigurable { public static final BlockEntitySynchronizationParameter> REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, "redstone_mode")); private final Class networkNodeClass; private N clientNode; private N removedNode; private static final Logger LOGGER = LogManager.getLogger(); protected NetworkNodeBlockEntity(BlockEntityType type, BlockPos pos, BlockState state, BlockEntitySynchronizationSpec syncSpec, Class networkNodeClass) { super(type, pos, state, syncSpec); this.networkNodeClass = networkNodeClass; } @Override public RedstoneMode getRedstoneMode() { return getNode().getRedstoneMode(); } @Override public void setRedstoneMode(RedstoneMode mode) { getNode().setRedstoneMode(mode); } @Override @Nonnull @SuppressWarnings("unchecked") public N getNode() { if (level.isClientSide) { if (clientNode == null) { clientNode = createNode(level, worldPosition); } return clientNode; } INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level); try { INetworkNode node = manager.getNode(worldPosition); if (node == null) { LOGGER.warn("Expected a node @ {} but couldn't find it, creating a new one...", worldPosition); node = createAndSetNode(manager); } return doCast(node); } catch (ClassCastException e) { LOGGER.warn("Node @ {} got desynced with it's block entity container, recreating", worldPosition, e); return (N) createAndSetNode(manager); } } private N doCast(INetworkNode node) { if (networkNodeClass == null) { return (N) node; } return networkNodeClass.cast(node); } private INetworkNode createAndSetNode(INetworkNodeManager manager) { INetworkNode node = createNode(level, worldPosition); manager.setNode(worldPosition, node); manager.markForSaving(); return node; } @Override public void clearRemoved() { super.clearRemoved(); if (!level.isClientSide) { INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level); if (manager.getNode(worldPosition) == null) { manager.setNode(worldPosition, createNode(level, worldPosition)); manager.markForSaving(); } } } @Override public void onRemovedNotDueToChunkUnload() { super.onRemovedNotDueToChunkUnload(); if (!level.isClientSide) { INetworkNodeManager manager = API.instance().getNetworkNodeManager((ServerLevel) level); INetworkNode node = manager.getNode(worldPosition); if (node != null) { try { removedNode = doCast(node); } catch (ClassCastException e) { removedNode = null; } } manager.removeNode(worldPosition); manager.markForSaving(); if (node != null && node.getNetwork() != null) { node.getNetwork().getNodeGraph().invalidate(Action.PERFORM, node.getNetwork().getLevel(), node.getNetwork().getPosition()); } } } public N getRemovedNode() { return removedNode; } public abstract N createNode(Level level, BlockPos pos); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkReceiverBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkReceiverNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class NetworkReceiverBlockEntity extends NetworkNodeBlockEntity { public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .build(); public NetworkReceiverBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.NETWORK_RECEIVER.get(), pos, state, SPEC, NetworkReceiverNetworkNode.class); } @Override @Nonnull public NetworkReceiverNetworkNode createNode(Level level, BlockPos pos) { return new NetworkReceiverNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/NetworkTransmitterBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkTransmitterNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.core.BlockPos; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; import java.util.Optional; public class NetworkTransmitterBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter DISTANCE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "network_transmitter_distance"), EntityDataSerializers.INT, 0, t -> t.getNode().getDistance()); public static final BlockEntitySynchronizationParameter, NetworkTransmitterBlockEntity> RECEIVER_DIMENSION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "network_transmitter_receiver_dimension"), RSSerializers.OPTIONAL_RESOURCE_LOCATION_SERIALIZER, Optional.empty(), t -> { if (t.getNode().getReceiverDimension() != null) { return Optional.of(t.getNode().getReceiverDimension().location()); } return Optional.empty(); }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(DISTANCE) .addWatchedParameter(RECEIVER_DIMENSION) .build(); public NetworkTransmitterBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.NETWORK_TRANSMITTER.get(), pos, state, SPEC, NetworkTransmitterNetworkNode.class); } @Override @Nonnull public NetworkTransmitterNetworkNode createNode(Level level, BlockPos pos) { return new NetworkTransmitterNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/RelayBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.RelayNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class RelayBlockEntity extends NetworkNodeBlockEntity { public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .build(); public RelayBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.RELAY.get(), pos, state, SPEC, RelayNetworkNode.class); } @Override @Nonnull public RelayNetworkNode createNode(Level level, BlockPos pos) { return new RelayNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/SecurityManagerBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.SecurityManagerNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class SecurityManagerBlockEntity extends NetworkNodeBlockEntity { public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .build(); public SecurityManagerBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.SECURITY_MANAGER.get(), pos, state, SPEC, SecurityManagerNetworkNode.class); } @Override @Nonnull public SecurityManagerNetworkNode createNode(Level level, BlockPos pos) { return new SecurityManagerNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/StorageBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.blockentity.config.IAccessType; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IPrioritizable; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class StorageBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter PRIORITY = IPrioritizable.createParameter(new ResourceLocation(RS.ID, "storage_priority")); public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "storage_compare")); public static final BlockEntitySynchronizationParameter WHITELIST_BLACKLIST = IWhitelistBlacklist.createParameter(new ResourceLocation(RS.ID, "storage_whitelist_blacklist")); public static final BlockEntitySynchronizationParameter ACCESS_TYPE = IAccessType.createParameter(new ResourceLocation(RS.ID, "storage_access_type")); public static final BlockEntitySynchronizationParameter STORED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "storage_stored"), RSSerializers.LONG_SERIALIZER, 0L, t -> t.getNode().getStorage() != null ? (long) t.getNode().getStorage().getStored() : 0); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(PRIORITY) .addWatchedParameter(COMPARE) .addWatchedParameter(WHITELIST_BLACKLIST) .addWatchedParameter(STORED) .addWatchedParameter(ACCESS_TYPE) .build(); private final ItemStorageType type; public StorageBlockEntity(ItemStorageType type, BlockPos pos, BlockState state) { super(getType(type), pos, state, SPEC, StorageNetworkNode.class); this.type = type; } public static BlockEntityType getType(ItemStorageType type) { return switch (type) { case ONE_K -> RSBlockEntities.ONE_K_STORAGE_BLOCK.get(); case FOUR_K -> RSBlockEntities.FOUR_K_STORAGE_BLOCK.get(); case SIXTEEN_K -> RSBlockEntities.SIXTEEN_K_STORAGE_BLOCK.get(); case SIXTY_FOUR_K -> RSBlockEntities.SIXTY_FOUR_K_STORAGE_BLOCK.get(); case CREATIVE -> RSBlockEntities.CREATIVE_STORAGE_BLOCK.get(); }; } public ItemStorageType getItemStorageType() { return type; } @Override @Nonnull public StorageNetworkNode createNode(Level level, BlockPos pos) { return new StorageNetworkNode(level, pos, type); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/StorageMonitorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode; import com.refinedmods.refinedstorage.blockentity.config.IComparable; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.config.ServerConfig; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; public class StorageMonitorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter COMPARE = IComparable.createParameter(new ResourceLocation(RS.ID, "storage_monitor_compare")); public static final BlockEntitySynchronizationParameter TYPE = IType.createParameter(new ResourceLocation(RS.ID, "storage_monitor_type")); private static final String NBT_TYPE = "Type"; private static final String NBT_FLUIDSTACK = "FluidStack"; private static final String NBT_STACK = "Stack"; private static final String NBT_AMOUNT = "Amount"; public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(COMPARE) .addWatchedParameter(TYPE) .build(); private int type; private int amount; @Nullable private ItemStack itemStack = ItemStack.EMPTY; @Nullable private FluidStack fluidStack = FluidStack.EMPTY; public StorageMonitorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.STORAGE_MONITOR.get(), pos, state, SPEC, StorageMonitorNetworkNode.class); } @Override public StorageMonitorNetworkNode createNode(Level level, BlockPos pos) { return new StorageMonitorNetworkNode(level, pos); } @Override public CompoundTag writeUpdate(CompoundTag tag) { super.writeUpdate(tag); ItemStack stack = getNode().getItemFilters().getStackInSlot(0); if (!stack.isEmpty()) { tag.put(NBT_STACK, stack.save(new CompoundTag())); } FluidStack fluid = getNode().getFluidFilters().getFluid(0); if (!fluid.isEmpty()) { tag.put(NBT_FLUIDSTACK, fluid.writeToNBT(new CompoundTag())); } tag.putInt(NBT_TYPE, getNode().getType()); tag.putInt(NBT_AMOUNT, getNode().getAmount()); return tag; } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); fluidStack = tag.contains(NBT_FLUIDSTACK) ? FluidStack.loadFluidStackFromNBT(tag.getCompound(NBT_FLUIDSTACK)) : FluidStack.EMPTY; itemStack = tag.contains(NBT_STACK) ? ItemStack.of(tag.getCompound(NBT_STACK)) : ItemStack.EMPTY; type = tag.contains(NBT_TYPE) ? tag.getInt(NBT_TYPE) : IType.ITEMS; amount = tag.getInt(NBT_AMOUNT); } public int getAmount() { return amount; } public int getStackType() { return type; } @Nullable public ItemStack getItemStack() { return itemStack; } @Nullable public FluidStack getFluidStack() { return fluidStack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/WirelessTransmitterBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.WirelessTransmitterNetworkNode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; public class WirelessTransmitterBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter RANGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "wireless_transmitter_range"), EntityDataSerializers.INT, 0, t -> t.getNode().getRange()); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(RANGE) .build(); public WirelessTransmitterBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.WIRELESS_TRANSMITTER.get(), pos, state, SPEC, WirelessTransmitterNetworkNode.class); } @Override @Nonnull public WirelessTransmitterNetworkNode createNode(Level level, BlockPos pos) { return new WirelessTransmitterNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IAccessType.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; public interface IAccessType { static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return new BlockEntitySynchronizationParameter<>(id, RSSerializers.ACCESS_TYPE_SERIALIZER, AccessType.INSERT_EXTRACT, t -> ((IAccessType) t.getNode()).getAccessType(), (t, v) -> ((IAccessType) t.getNode()).setAccessType(v)); } AccessType getAccessType(); void setAccessType(AccessType accessType); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IComparable.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; public interface IComparable { static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IComparable) t.getNode()).getCompare(), (t, v) -> ((IComparable) t.getNode()).setCompare(v)); } int getCompare(); void setCompare(int compare); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IPrioritizable.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; public interface IPrioritizable { static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IPrioritizable) t.getNode()).getPriority(), (t, v) -> ((IPrioritizable) t.getNode()).setPriority(v)); } int getPriority(); void setPriority(int priority); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IRedstoneConfigurable.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; public interface IRedstoneConfigurable { RedstoneMode getRedstoneMode(); void setRedstoneMode(RedstoneMode mode); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IType.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationClientListener; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; public interface IType { int ITEMS = 0; int FLUIDS = 1; static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id, @Nullable BlockEntitySynchronizationClientListener clientListener) { return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, ITEMS, t -> ((IType) t.getNode()).getType(), (t, v) -> { if (v == IType.ITEMS || v == IType.FLUIDS) { ((IType) t.getNode()).setType(v); } }, clientListener); } static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return createParameter(id, null); } int getType(); void setType(int type); IItemHandlerModifiable getItemFilters(); FluidInventory getFluidFilters(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/IWhitelistBlacklist.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandler; public interface IWhitelistBlacklist { int WHITELIST = 0; int BLACKLIST = 1; static > BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, 0, t -> ((IWhitelistBlacklist) t.getNode()).getWhitelistBlacklistMode(), (t, v) -> { if (v == WHITELIST || v == BLACKLIST) { ((IWhitelistBlacklist) t.getNode()).setWhitelistBlacklistMode(v); } }); } static boolean acceptsItem(IItemHandler filters, int mode, int compare, ItemStack stack) { if (mode == WHITELIST) { for (int i = 0; i < filters.getSlots(); ++i) { ItemStack slot = filters.getStackInSlot(i); if (API.instance().getComparer().isEqual(slot, stack, compare)) { return true; } } return false; } else if (mode == BLACKLIST) { for (int i = 0; i < filters.getSlots(); ++i) { ItemStack slot = filters.getStackInSlot(i); if (API.instance().getComparer().isEqual(slot, stack, compare)) { return false; } } return true; } return false; } static boolean acceptsFluid(FluidInventory filters, int mode, int compare, FluidStack stack) { if (mode == WHITELIST) { for (int i = 0; i < filters.getSlots(); ++i) { FluidStack slot = filters.getFluid(i); if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, compare)) { return true; } } return false; } else if (mode == BLACKLIST) { for (int i = 0; i < filters.getSlots(); ++i) { FluidStack slot = filters.getFluid(i); if (!slot.isEmpty() && API.instance().getComparer().isEqual(slot, stack, compare)) { return false; } } return true; } return false; } int getWhitelistBlacklistMode(); void setWhitelistBlacklistMode(int mode); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/config/RedstoneMode.java ================================================ package com.refinedmods.refinedstorage.blockentity.config; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; public enum RedstoneMode { IGNORE, HIGH, LOW; private static final String NBT = "RedstoneMode"; public static RedstoneMode read(CompoundTag tag) { if (tag.contains(RedstoneMode.NBT)) { return getById(tag.getInt(NBT)); } return IGNORE; } public static RedstoneMode getById(int id) { return id < 0 || id >= values().length ? IGNORE : values()[id]; } public static BlockEntitySynchronizationParameter createParameter(ResourceLocation id) { return new BlockEntitySynchronizationParameter<>(id, EntityDataSerializers.INT, IGNORE.ordinal(), t -> t.getRedstoneMode().ordinal(), (t, v) -> t.setRedstoneMode(RedstoneMode.getById(v))); } public boolean isEnabled(boolean powered) { switch (this) { case IGNORE: return true; case HIGH: return powered; case LOW: return !powered; default: return false; } } public void write(CompoundTag tag) { tag.putInt(NBT, ordinal()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/CraftingMonitorBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity.craftingmonitor; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.apiimpl.network.node.CraftingMonitorNetworkNode; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import net.minecraft.core.BlockPos; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nonnull; import java.util.Optional; import java.util.UUID; public class CraftingMonitorBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter, CraftingMonitorBlockEntity> TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafting_monitor_tab_selected"), EntityDataSerializers.OPTIONAL_UUID, Optional.empty(), t -> t.getNode().getTabSelected(), (t, v) -> { if (v.isPresent() && t.getNode().getTabSelected().isPresent() && v.get().equals(t.getNode().getTabSelected().get())) { t.getNode().setTabSelected(Optional.empty()); } else { t.getNode().setTabSelected(v); } t.getNode().markDirty(); }); public static final BlockEntitySynchronizationParameter TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "crafting_monitor_tab_page"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabPage(), (t, v) -> { if (v >= 0) { t.getNode().setTabPage(v); t.getNode().markDirty(); } }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(TAB_SELECTED) .addWatchedParameter(TAB_PAGE) .build(); public CraftingMonitorBlockEntity(BlockPos pos, BlockState state) { super(RSBlockEntities.CRAFTING_MONITOR.get(), pos, state, SPEC, CraftingMonitorNetworkNode.class); } @Override @Nonnull public CraftingMonitorNetworkNode createNode(Level level, BlockPos pos) { return new CraftingMonitorNetworkNode(level, pos); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/ICraftingMonitor.java ================================================ package com.refinedmods.refinedstorage.blockentity.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import javax.annotation.Nullable; import java.util.Collection; import java.util.Optional; import java.util.UUID; public interface ICraftingMonitor { int TABS_PER_PAGE = 7; Component getTitle(); void onCancelled(ServerPlayer player, @Nullable UUID id); BlockEntitySynchronizationParameter getRedstoneModeParameter(); Collection getTasks(); @Nullable ICraftingManager getCraftingManager(); boolean isActiveOnClient(); void onClosed(Player player); Optional getTabSelected(); int getTabPage(); void onTabSelectionChanged(Optional taskId); void onTabPageChanged(int page); int getSlotId(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/craftingmonitor/WirelessCraftingMonitor.java ================================================ package com.refinedmods.refinedstorage.blockentity.craftingmonitor; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.NetworkItem; import com.refinedmods.refinedstorage.item.WirelessCraftingMonitorItem; import com.refinedmods.refinedstorage.network.craftingmonitor.WirelessCraftingMonitorSettingsUpdateMessage; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.UUID; public class WirelessCraftingMonitor implements ICraftingMonitor { private final ItemStack stack; @Nullable private final MinecraftServer server; private final ResourceKey nodeDimension; private final BlockPos nodePos; private final PlayerSlot slot; private int tabPage; private Optional tabSelected; public WirelessCraftingMonitor(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) { this.stack = stack; this.server = server; this.slot = slot; this.nodeDimension = NetworkItem.getDimension(stack); this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack)); this.tabPage = WirelessCraftingMonitorItem.getTabPage(stack); this.tabSelected = WirelessCraftingMonitorItem.getTabSelected(stack); } public void setSettings(Optional tabSelected, int tabPage) { this.tabSelected = tabSelected; this.tabPage = tabPage; WirelessCraftingMonitorItem.setTabSelected(stack, tabSelected); WirelessCraftingMonitorItem.setTabPage(stack, tabPage); } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.wireless_crafting_monitor"); } @Override public void onCancelled(ServerPlayer player, @Nullable UUID id) { INetwork network = getNetwork(); if (network != null) { network.getItemGridHandler().onCraftingCancelRequested(player, id); } } @Override public BlockEntitySynchronizationParameter getRedstoneModeParameter() { return null; } @Override public Collection getTasks() { INetwork network = getNetwork(); if (network != null) { return network.getCraftingManager().getTasks(); } return Collections.emptyList(); } @Nullable @Override public ICraftingManager getCraftingManager() { INetwork network = getNetwork(); if (network != null) { return network.getCraftingManager(); } return null; } private INetwork getNetwork() { Level level = server.getLevel(nodeDimension); if (level == null) { return null; } if (!level.isLoaded(nodePos)) { return null; } return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos))); } public ItemStack getStack() { return stack; } @Override public boolean isActiveOnClient() { return true; } @Override public void onClosed(Player player) { INetwork network = getNetwork(); if (network != null) { network.getNetworkItemManager().close(player); } } @Override public Optional getTabSelected() { return tabSelected; } @Override public int getTabPage() { return tabPage; } @Override public void onTabSelectionChanged(Optional taskId) { if (taskId.isPresent() && tabSelected.isPresent() && taskId.get().equals(tabSelected.get())) { this.tabSelected = Optional.empty(); } else { this.tabSelected = taskId; } RS.NETWORK_HANDLER.sendToServer(new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage)); } @Override public void onTabPageChanged(int page) { if (page >= 0) { this.tabPage = page; RS.NETWORK_HANDLER.sendToServer(new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage)); } } @Override public int getSlotId() { return slot.getSlotIdInPlayerInventory(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationClientListener.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; public interface BlockEntitySynchronizationClientListener { void onChanged(boolean initial, T value); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationManager.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterUpdateMessage; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; public class BlockEntitySynchronizationManager { private static final Map REGISTRY = new HashMap<>(); private final BlockEntity blockEntity; private final List parameters; private final List watchedParameters; private final List watchers = new CopyOnWriteArrayList<>(); public BlockEntitySynchronizationManager(BlockEntity blockEntity, BlockEntitySynchronizationSpec spec) { this.blockEntity = blockEntity; this.parameters = spec.getParameters(); this.watchedParameters = spec.getWatchedParameters(); } public BlockEntity getBlockEntity() { return blockEntity; } public List getParameters() { return parameters; } public List getWatchedParameters() { return watchedParameters; } public void addWatcher(BlockEntitySynchronizationWatcher listener) { watchers.add(listener); } public void removeWatcher(BlockEntitySynchronizationWatcher listener) { watchers.remove(listener); } public void sendParameterToWatchers(BlockEntitySynchronizationParameter parameter) { watchers.forEach(l -> l.sendParameter(false, parameter)); } // Synchronized so we don't conflict with addons that reuse this register method in parallel. public synchronized static void registerParameter(BlockEntitySynchronizationParameter parameter) { REGISTRY.put(parameter.getId(), parameter); } public static BlockEntitySynchronizationParameter getParameter(ResourceLocation id) { return REGISTRY.get(id); } public static void setParameter(BlockEntitySynchronizationParameter parameter, Object value) { RS.NETWORK_HANDLER.sendToServer(new BlockEntitySynchronizationParameterUpdateMessage(parameter, value)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationParameter.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; import java.util.HashSet; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Function; public class BlockEntitySynchronizationParameter { private static final Set HAD = new HashSet<>(); private final ResourceLocation id; private final EntityDataSerializer serializer; private final Function valueProducer; @Nullable private final BiConsumer valueConsumer; @Nullable private final BlockEntitySynchronizationClientListener listener; private T value; public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer serializer, T defaultValue, Function producer) { this(id, serializer, defaultValue, producer, null); } public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer serializer, T defaultValue, Function producer, @Nullable BiConsumer consumer) { this(id, serializer, defaultValue, producer, consumer, null); } public BlockEntitySynchronizationParameter(ResourceLocation id, EntityDataSerializer serializer, T defaultValue, Function producer, @Nullable BiConsumer consumer, @Nullable BlockEntitySynchronizationClientListener listener) { if (!HAD.add(id)) { throw new IllegalArgumentException("Duplicate BlockEntitySynchronizationParameter: " + id); } this.id = id; this.value = defaultValue; this.serializer = serializer; this.valueProducer = producer; this.valueConsumer = consumer; this.listener = listener; } public ResourceLocation getId() { return id; } public EntityDataSerializer getSerializer() { return serializer; } public Function getValueProducer() { return valueProducer; } @Nullable public BiConsumer getValueConsumer() { return valueConsumer; } public void setValue(boolean initial, T value) { this.value = value; if (listener != null) { listener.onChanged(initial, value); } } public T getValue() { return value; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationSpec.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; import java.util.ArrayList; import java.util.Collections; import java.util.List; public final class BlockEntitySynchronizationSpec { private final List parameters; private final List watchedParameters; public BlockEntitySynchronizationSpec(List parameters, List watchedParameters) { this.parameters = Collections.unmodifiableList(parameters); this.watchedParameters = Collections.unmodifiableList(watchedParameters); } public List getParameters() { return parameters; } public List getWatchedParameters() { return watchedParameters; } public static Builder builder() { return new Builder(); } public static class Builder { private final List parameters = new ArrayList<>(); private final List watchedParameters = new ArrayList<>(); public Builder addParameter(BlockEntitySynchronizationParameter parameter) { parameters.add(parameter); return this; } public Builder addWatchedParameter(BlockEntitySynchronizationParameter parameter) { addParameter(parameter); watchedParameters.add(parameter); return this; } public BlockEntitySynchronizationSpec build() { return new BlockEntitySynchronizationSpec(parameters, watchedParameters); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/BlockEntitySynchronizationWatcher.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterMessage; import net.minecraft.server.level.ServerPlayer; public class BlockEntitySynchronizationWatcher { private final ServerPlayer player; private final BlockEntitySynchronizationManager manager; private boolean sentInitial; private Object[] cache; public BlockEntitySynchronizationWatcher(ServerPlayer player, BlockEntitySynchronizationManager manager) { this.player = player; this.manager = manager; if (manager != null) { this.manager.addWatcher(this); this.cache = new Object[manager.getWatchedParameters().size()]; } } public ServerPlayer getPlayer() { return player; } public void onClosed() { this.manager.removeWatcher(this); } public void detectAndSendChanges() { if (!sentInitial) { manager.getParameters().forEach(p -> sendParameter(true, p)); sentInitial = true; } else { for (int i = 0; i < manager.getWatchedParameters().size(); ++i) { BlockEntitySynchronizationParameter parameter = manager.getWatchedParameters().get(i); Object real = parameter.getValueProducer().apply(manager.getBlockEntity()); Object cached = cache[i]; if (!real.equals(cached)) { cache[i] = real; // Avoid sending watched parameter twice (after initial packet) if (cached != null) { sendParameter(false, parameter); } } } } } public void sendParameter(boolean initial, BlockEntitySynchronizationParameter parameter) { RS.NETWORK_HANDLER.sendTo(player, new BlockEntitySynchronizationParameterMessage( parameter, parameter.getValueProducer().apply(manager.getBlockEntity()), initial )); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/data/RSSerializers.java ================================================ package com.refinedmods.refinedstorage.blockentity.data; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.blockentity.ClientNode; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import java.util.*; public final class RSSerializers { public static final EntityDataSerializer> CLIENT_NODE_SERIALIZER = new EntityDataSerializer>() { @Override public void write(FriendlyByteBuf buf, List nodes) { buf.writeInt(nodes.size()); for (ClientNode node : nodes) { buf.writeItem(node.getStack()); buf.writeInt(node.getAmount()); buf.writeInt(node.getEnergyUsage()); } } @Override public List read(FriendlyByteBuf buf) { List nodes = new ArrayList<>(); int size = buf.readInt(); for (int i = 0; i < size; ++i) { nodes.add(new ClientNode(buf.readItem(), buf.readInt(), buf.readInt())); } return nodes; } @Override public EntityDataAccessor> createAccessor(int id) { return null; } @Override public List copy(List value) { return value; } }; public static final EntityDataSerializer FLUID_STACK_SERIALIZER = new EntityDataSerializer() { @Override public void write(FriendlyByteBuf buf, FluidStack value) { value.writeToPacket(buf); } @Override public FluidStack read(FriendlyByteBuf buf) { return FluidStack.readFromPacket(buf); } @Override public EntityDataAccessor createAccessor(int id) { return null; } @Override public FluidStack copy(FluidStack value) { return value; } }; public static final EntityDataSerializer ACCESS_TYPE_SERIALIZER = new EntityDataSerializer() { @Override public void write(FriendlyByteBuf buf, AccessType value) { buf.writeInt(value.getId()); } @Override public AccessType read(FriendlyByteBuf buf) { return AccessTypeUtils.getAccessType(buf.readInt()); } @Override public EntityDataAccessor createAccessor(int id) { return null; } @Override public AccessType copy(AccessType value) { return value; } }; public static final EntityDataSerializer LONG_SERIALIZER = new EntityDataSerializer() { @Override public void write(FriendlyByteBuf buf, Long value) { buf.writeLong(value); } @Override public Long read(FriendlyByteBuf buf) { return buf.readLong(); } @Override public EntityDataAccessor createAccessor(int id) { return null; } @Override public Long copy(Long value) { return value; } }; public static final EntityDataSerializer> OPTIONAL_RESOURCE_LOCATION_SERIALIZER = new EntityDataSerializer>() { @Override public void write(FriendlyByteBuf buf, Optional value) { buf.writeBoolean(value.isPresent()); value.ifPresent(buf::writeResourceLocation); } @Override public Optional read(FriendlyByteBuf buf) { if (!buf.readBoolean()) { return Optional.empty(); } return Optional.of(buf.readResourceLocation()); } @Override public EntityDataAccessor> createAccessor(int id) { return null; } @Override public Optional copy(Optional value) { return value; } }; public static final EntityDataSerializer>> LIST_OF_SET_SERIALIZER = new EntityDataSerializer>>() { @Override public void write(FriendlyByteBuf buf, List> value) { buf.writeInt(value.size()); for (Set values : value) { buf.writeInt(values.size()); values.forEach(buf::writeResourceLocation); } } @Override public List> read(FriendlyByteBuf buf) { List> value = new ArrayList<>(); int size = buf.readInt(); for (int i = 0; i < size; ++i) { int setSize = buf.readInt(); Set values = new HashSet<>(); for (int j = 0; j < setSize; ++j) { values.add(buf.readResourceLocation()); } value.add(values); } return value; } @Override public EntityDataAccessor>> createAccessor(int id) { return null; } @Override public List> copy(List> value) { return value; } }; private RSSerializers() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/GridBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.data.RSSerializers; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.energy.IEnergyStorage; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Set; public class GridBlockEntity extends NetworkNodeBlockEntity { public static final BlockEntitySynchronizationParameter EXACT_PATTERN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_exact_mode"), EntityDataSerializers.BOOLEAN, true, t -> t.getNode().isExactPattern(), (t, v) -> { t.getNode().setExactPattern(v); t.getNode().markDirty(); }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.updateExactPattern(p))); public static final BlockEntitySynchronizationParameter PROCESSING_TYPE = IType.createParameter(new ResourceLocation(RS.ID, "grid_processing_type"), (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init)); public static final BlockEntitySynchronizationParameter VIEW_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_view_type"), EntityDataSerializers.INT, 0, t -> t.getNode().getViewType(), (t, v) -> { if (IGrid.isValidViewType(v)) { t.getNode().setViewType(v); t.getNode().markDirty(); } }, (initial, p) -> trySortGrid(initial)); public static final BlockEntitySynchronizationParameter>, 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)); public static final BlockEntitySynchronizationParameter>, 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)); public static final BlockEntitySynchronizationParameter SORTING_DIRECTION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_sorting_direction"), EntityDataSerializers.INT, 0, t -> t.getNode().getSortingDirection(), (t, v) -> { if (IGrid.isValidSortingDirection(v)) { t.getNode().setSortingDirection(v); t.getNode().markDirty(); } }, (initial, p) -> trySortGrid(initial)); public static final BlockEntitySynchronizationParameter SORTING_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_sorting_type"), EntityDataSerializers.INT, 0, t -> t.getNode().getSortingType(), (t, v) -> { if (IGrid.isValidSortingType(v)) { t.getNode().setSortingType(v); t.getNode().markDirty(); } }, (initial, p) -> trySortGrid(initial)); public static final BlockEntitySynchronizationParameter TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_tab_selected"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabSelected(), (t, v) -> { t.getNode().setTabSelected(v == t.getNode().getTabSelected() ? -1 : v); t.getNode().markDirty(); }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort())); public static final BlockEntitySynchronizationParameter TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_tab_page"), EntityDataSerializers.INT, 0, t -> t.getNode().getTabPage(), (t, v) -> { if (v >= 0 && v <= t.getNode().getTotalTabPages()) { t.getNode().setTabPage(v); t.getNode().markDirty(); } }); public static final BlockEntitySynchronizationParameter PROCESSING_PATTERN = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_processing_pattern"), EntityDataSerializers.BOOLEAN, false, t -> t.getNode().isProcessingPattern(), (t, v) -> { t.getNode().setProcessingPattern(v); t.getNode().clearMatrix(); t.getNode().markDirty(); }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init)); public static final BlockEntitySynchronizationParameter SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_size"), EntityDataSerializers.INT, 0, t -> t.getNode().getSize(), (t, v) -> { if (IGrid.isValidSize(v)) { t.getNode().setSize(v); t.getNode().markDirty(); } }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.resize(grid.getMinecraft(), grid.width, grid.height))); public static final BlockEntitySynchronizationParameter SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "grid_search_box_mode"), EntityDataSerializers.INT, 0, t -> t.getNode().getSearchBoxMode(), (t, v) -> { if (IGrid.isValidSearchBoxMode(v)) { t.getNode().setSearchBoxMode(v); t.getNode().markDirty(); } }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getSearchField().setMode(p))); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(VIEW_TYPE) .addWatchedParameter(SORTING_DIRECTION) .addWatchedParameter(SORTING_TYPE) .addWatchedParameter(SEARCH_BOX_MODE) .addWatchedParameter(SIZE) .addWatchedParameter(TAB_SELECTED) .addWatchedParameter(TAB_PAGE) .addWatchedParameter(EXACT_PATTERN) .addWatchedParameter(PROCESSING_PATTERN) .addWatchedParameter(PROCESSING_TYPE) .addParameter(ALLOWED_ITEM_TAGS) .addParameter(ALLOWED_FLUID_TAGS) .build(); public static BlockEntityType getType(GridType type) { return switch (type) { case NORMAL -> RSBlockEntities.GRID.get(); case CRAFTING -> RSBlockEntities.CRAFTING_GRID.get(); case PATTERN -> RSBlockEntities.PATTERN_GRID.get(); case FLUID -> RSBlockEntities.FLUID_GRID.get(); }; } public static void trySortGrid(boolean initial) { if (!initial) { BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } } private final GridType type; public GridBlockEntity(GridType type, BlockPos pos, BlockState state) { super(getType(type), pos, state, SPEC, GridNetworkNode.class); this.type = type; } @Override @Nonnull public GridNetworkNode createNode(Level level, BlockPos pos) { return new GridNetworkNode(level, pos, type); } public IItemHandler getInventory() { if (type == GridType.PATTERN) { return getNode().getPatterns(); } return null; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/WirelessFluidGrid.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.grid.*; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.FluidGridStorageCacheListener; import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.NetworkItem; import com.refinedmods.refinedstorage.item.WirelessFluidGridItem; import com.refinedmods.refinedstorage.network.grid.WirelessFluidGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class WirelessFluidGrid implements INetworkAwareGrid { @Nullable private final MinecraftServer server; private final ResourceKey nodeDimension; private final BlockPos nodePos; private final PlayerSlot slot; private final List filters = new ArrayList<>(); private final List tabs = new ArrayList<>(); private ItemStack stack; private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs) .addListener(((handler, slot, reading) -> { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } StackUtils.writeItems(handler, 0, stack.getTag()); })); private int sortingType; private int sortingDirection; private int searchBoxMode; private int tabSelected; private int tabPage; private int size; public WirelessFluidGrid(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) { this.stack = stack; this.server = server; this.nodeDimension = NetworkItem.getDimension(stack); this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack)); this.slot = slot; this.sortingType = WirelessFluidGridItem.getSortingType(stack); this.sortingDirection = WirelessFluidGridItem.getSortingDirection(stack); this.searchBoxMode = WirelessFluidGridItem.getSearchBoxMode(stack); this.tabSelected = WirelessFluidGridItem.getTabSelected(stack); this.tabPage = WirelessFluidGridItem.getTabPage(stack); this.size = WirelessFluidGridItem.getSize(stack); if (stack.hasTag()) { StackUtils.readItems(filter, 0, stack.getTag()); } } public ItemStack getStack() { return stack; } @Override public GridType getGridType() { return GridType.FLUID; } @Override @Nullable public INetwork getNetwork() { Level level = server.getLevel(nodeDimension); if (level == null) { return null; } if (!level.isLoaded(nodePos)) { return null; } return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos))); } @Override public IStorageCacheListener createListener(ServerPlayer player) { return new FluidGridStorageCacheListener(player, getNetwork()); } @Nullable @Override public IStorageCache getStorageCache() { INetwork network = getNetwork(); return network != null ? network.getFluidStorageCache() : null; } @Nullable @Override public IItemGridHandler getItemHandler() { return null; } @Nullable @Override public IFluidGridHandler getFluidHandler() { INetwork network = getNetwork(); return network != null ? network.getFluidGridHandler() : null; } @Override public void addCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public void removeCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.fluid_grid"); } @Override public int getViewType() { return 0; } @Override public int getSortingType() { return sortingType; } @Override public int getSortingDirection() { return sortingDirection; } @Override public int getSearchBoxMode() { return searchBoxMode; } @Override public int getTabSelected() { return tabSelected; } @Override public int getTabPage() { return Math.min(tabPage, getTotalTabPages()); } @Override public int getTotalTabPages() { return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE); } @Override public int getSize() { return size; } @Override public void onViewTypeChanged(int type) { // NO OP } @Override public void onSortingTypeChanged(int type) { RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingType = type; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSortingDirectionChanged(int direction) { RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingDirection = direction; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSearchBoxModeChanged(int searchBoxMode) { RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage())); this.searchBoxMode = searchBoxMode; } @Override public void onSizeChanged(int size) { RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage())); this.size = size; BaseScreen.executeLater(GridScreen.class, BaseScreen::init); } @Override public void onTabSelectionChanged(int tab) { this.tabSelected = tab == tabSelected ? -1 : tab; RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage())); BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onTabPageChanged(int page) { if (page >= 0 && page <= getTotalTabPages()) { RS.NETWORK_HANDLER.sendToServer(new WirelessFluidGridSettingsUpdateMessage(getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page)); this.tabPage = page; } } @Override public List getFilters() { return filters; } @Override public List getTabs() { return tabs; } @Override public IItemHandlerModifiable getFilter() { return filter; } @Override public CraftingContainer getCraftingMatrix() { return null; } @Override public ResultContainer getCraftingResult() { return null; } @Override public void onCraftingMatrixChanged() { // NO OP } @Override public void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { // NO OP } @Override public void onClear(Player player) { // NO OP } @Override public void onCraftedShift(Player player) { // NO OP } @Override public void onRecipeTransfer(Player player, ItemStack[][] recipe) { // NO OP } @Override public boolean isGridActive() { return true; } @Override public int getSlotId() { return slot.getSlotIdInPlayerInventory(); } @Override public void onClosed(Player player) { INetwork network = getNetwork(); if (network != null) { network.getNetworkItemManager().close(player); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/WirelessGrid.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.grid.*; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.ItemGridStorageCacheListener; import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.NetworkItem; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.network.grid.WirelessGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class WirelessGrid implements INetworkAwareGrid { @Nullable private final MinecraftServer server; private final ResourceKey nodeDimension; private final BlockPos nodePos; private final PlayerSlot slot; private final List filters = new ArrayList<>(); private final List tabs = new ArrayList<>(); private ItemStack stack; private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs) .addListener((handler, slot, reading) -> { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } StackUtils.writeItems(handler, 0, stack.getTag()); }); private int viewType; private int sortingType; private int sortingDirection; private int searchBoxMode; private int tabSelected; private int tabPage; private int size; public WirelessGrid(ItemStack stack, @Nullable MinecraftServer server, PlayerSlot slot) { this.stack = stack; this.server = server; this.nodeDimension = NetworkItem.getDimension(stack); this.nodePos = new BlockPos(NetworkItem.getX(stack), NetworkItem.getY(stack), NetworkItem.getZ(stack)); this.slot = slot; this.viewType = WirelessGridItem.getViewType(stack); this.sortingType = WirelessGridItem.getSortingType(stack); this.sortingDirection = WirelessGridItem.getSortingDirection(stack); this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack); this.tabSelected = WirelessGridItem.getTabSelected(stack); this.tabPage = WirelessGridItem.getTabPage(stack); this.size = WirelessGridItem.getSize(stack); if (stack.hasTag()) { StackUtils.readItems(filter, 0, stack.getTag()); } } public ItemStack getStack() { return stack; } @Override public GridType getGridType() { return GridType.NORMAL; } @Override @Nullable public INetwork getNetwork() { Level level = server.getLevel(nodeDimension); if (level == null) { return null; } if (!level.isLoaded(nodePos)) { return null; } return NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(level.getBlockEntity(nodePos))); } @Override public IStorageCacheListener createListener(ServerPlayer player) { return new ItemGridStorageCacheListener(player, getNetwork()); } @Nullable @Override public IStorageCache getStorageCache() { INetwork network = getNetwork(); return network != null ? network.getItemStorageCache() : null; } @Nullable @Override public IItemGridHandler getItemHandler() { INetwork network = getNetwork(); return network != null ? network.getItemGridHandler() : null; } @Nullable @Override public IFluidGridHandler getFluidHandler() { return null; } @Override public void addCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public void removeCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.grid"); } @Override public int getViewType() { return viewType; } @Override public int getSortingType() { return sortingType; } @Override public int getSortingDirection() { return sortingDirection; } @Override public int getSearchBoxMode() { return searchBoxMode; } @Override public int getTabSelected() { return tabSelected; } @Override public int getTabPage() { return Math.min(tabPage, getTotalTabPages()); } @Override public int getTotalTabPages() { return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE); } @Override public int getSize() { return size; } @Override public void onViewTypeChanged(int type) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(type, getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.viewType = type; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSortingTypeChanged(int type) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingType = type; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSortingDirectionChanged(int direction) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingDirection = direction; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSearchBoxModeChanged(int searchBoxMode) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage())); this.searchBoxMode = searchBoxMode; } @Override public void onSizeChanged(int size) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage())); this.size = size; BaseScreen.executeLater(GridScreen.class, BaseScreen::init); } @Override public void onTabSelectionChanged(int tab) { this.tabSelected = tab == tabSelected ? -1 : tab; RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage())); BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onTabPageChanged(int page) { if (page >= 0 && page <= getTotalTabPages()) { RS.NETWORK_HANDLER.sendToServer(new WirelessGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page)); this.tabPage = page; } } @Override public List getFilters() { return filters; } @Override public List getTabs() { return tabs; } @Override public IItemHandlerModifiable getFilter() { return filter; } @Override public CraftingContainer getCraftingMatrix() { return null; } @Override public ResultContainer getCraftingResult() { return null; } @Override public void onCraftingMatrixChanged() { // NO OP } @Override public void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { // NO OP } @Override public void onClear(Player player) { // NO OP } @Override public void onCraftedShift(Player player) { // NO OP } @Override public void onRecipeTransfer(Player player, ItemStack[][] recipe) { // NO OP } @Override public boolean isGridActive() { return true; } @Override public int getSlotId() { return slot.getSlotIdInPlayerInventory(); } @Override public void onClosed(Player player) { INetwork network = getNetwork(); if (network != null) { network.getNetworkItemManager().close(player); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/IPortableGrid.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid.portable; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; public interface IPortableGrid { @Nullable IStorageCache getCache(); default IStorageCache getItemCache() { return getCache(); } default IStorageCache getFluidCache() { return getCache(); } @Nullable IStorageDisk getStorage(); default IStorageDisk getItemStorage() { return getStorage(); } default IStorageDisk getFluidStorage() { return getStorage(); } void drainEnergy(int energy); int getEnergy(); BaseItemHandler getDiskInventory(); IItemHandlerModifiable getFilter(); IStorageTracker getItemStorageTracker(); IStorageTracker getFluidStorageTracker(); boolean isGridActive(); PortableGridDiskState getDiskState(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGrid.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid.portable; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableFluidStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableItemStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableFluidGridStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableItemGridStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableFluidStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableItemStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import com.refinedmods.refinedstorage.network.grid.PortableGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; public class PortableGrid implements IGrid, IPortableGrid, IStorageDiskContainerContext { static final String NBT_ITEM_STORAGE_TRACKER_ID = "ItemStorageTrackerId"; static final String NBT_FLUID_STORAGE_TRACKER_ID = "FluidStorageTrackerId"; private final PortableItemGridHandler itemHandler = new PortableItemGridHandler(this, this); private final PortableFluidGridHandler fluidHandler = new PortableFluidGridHandler(this); private final PlayerSlot slot; private final List filters = new ArrayList<>(); private final List tabs = new ArrayList<>(); @Nullable private IStorageDisk storage; @Nullable private IStorageCache cache; @Nullable private Player player; private ItemStack stack; private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs) .addListener((handler, slot, reading) -> { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } StackUtils.writeItems(handler, 0, stack.getTag()); }); private int sortingType; private int sortingDirection; private int searchBoxMode; private int tabSelected; private int tabPage; private int size; private ItemStorageTracker itemStorageTracker; private UUID itemStorageTrackerId; private FluidStorageTracker fluidStorageTracker; private UUID fluidStorageTrackerId; public PortableGrid(@Nullable Player player, ItemStack stack, PlayerSlot slot) { this.player = player; this.stack = stack; this.slot = slot; this.sortingType = WirelessGridItem.getSortingType(stack); this.sortingDirection = WirelessGridItem.getSortingDirection(stack); this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack); this.tabSelected = WirelessGridItem.getTabSelected(stack); this.tabPage = WirelessGridItem.getTabPage(stack); this.size = WirelessGridItem.getSize(stack); if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } if (player != null) { //baked model does not need a storage tracker if (stack.getTag().contains(NBT_ITEM_STORAGE_TRACKER_ID)) { itemStorageTrackerId = stack.getTag().getUUID(NBT_ITEM_STORAGE_TRACKER_ID); } else { UUID id = UUID.randomUUID(); stack.getTag().putUUID(NBT_ITEM_STORAGE_TRACKER_ID, id); itemStorageTrackerId = id; } if (stack.getTag().contains(NBT_FLUID_STORAGE_TRACKER_ID)) { fluidStorageTrackerId = stack.getTag().getUUID(NBT_FLUID_STORAGE_TRACKER_ID); } else { UUID id = UUID.randomUUID(); stack.getTag().putUUID(NBT_FLUID_STORAGE_TRACKER_ID, id); fluidStorageTrackerId = id; } } StackUtils.readItems(disk, 4, stack.getTag()); StackUtils.readItems(filter, 0, stack.getTag()); } public void onOpen() { drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()); } private final BaseItemHandler disk = new BaseItemHandler(1) .addValidator(new StorageDiskItemValidator()) .addListener(((handler, slot, reading) -> { if (player != null && !player.level().isClientSide) { ItemStack diskStack = handler.getStackInSlot(slot); if (diskStack.isEmpty()) { storage = null; cache = null; } else { IStorageDisk diskInSlot = API.instance().getStorageDiskManager((ServerLevel) player.level()).getByStack(getDiskInventory().getStackInSlot(0)); if (diskInSlot != null) { StorageType type = ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType(); if (type == StorageType.ITEM) { storage = new PortableItemStorageDisk(diskInSlot, PortableGrid.this); cache = new PortableItemStorageCache(PortableGrid.this); } else if (type == StorageType.FLUID) { storage = new PortableFluidStorageDisk(diskInSlot, PortableGrid.this); cache = new PortableFluidStorageCache(PortableGrid.this); } storage.setSettings(null, PortableGrid.this); } else { storage = null; cache = null; } } if (cache != null) { cache.invalidate(InvalidateCause.DISK_INVENTORY_CHANGED); } StackUtils.writeItems(handler, 4, stack.getTag()); } })); public ItemStack getStack() { return stack; } @Override @Nullable public IStorageCache getCache() { return cache; } @Override @Nullable public IStorageDisk getStorage() { return storage; } @Override public void drainEnergy(int energy) { if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE) { IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyStorage != null) { energyStorage.extractEnergy(energy, false); } } } @Override public int getEnergy() { if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE) { return Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)) .map(IEnergyStorage::getEnergyStored) .orElse(RS.SERVER_CONFIG.getPortableGrid().getCapacity()); } return RS.SERVER_CONFIG.getPortableGrid().getCapacity(); } @Override public BaseItemHandler getDiskInventory() { return disk; } public Player getPlayer() { return player; } @Override public GridType getGridType() { return (getDiskInventory().getStackInSlot(0).isEmpty() || ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType() == StorageType.ITEM) ? GridType.NORMAL : GridType.FLUID; } @Nullable @Override public IStorageCache getStorageCache() { return storage != null ? cache : null; } @Override public IStorageCacheListener createListener(ServerPlayer player) { return getGridType() == GridType.FLUID ? new PortableFluidGridStorageCacheListener(this, player) : new PortableItemGridStorageCacheListener(this, player); } @Nullable @Override public IItemGridHandler getItemHandler() { return itemHandler; } @Nullable @Override public IFluidGridHandler getFluidHandler() { return fluidHandler; } @Override public void addCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public void removeCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.portable_grid"); } @Override public int getViewType() { return -1; } @Override public int getSortingType() { return sortingType; } @Override public int getSortingDirection() { return sortingDirection; } @Override public int getSearchBoxMode() { return searchBoxMode; } @Override public int getTabSelected() { return tabSelected; } @Override public int getTabPage() { return Math.min(tabPage, getTotalTabPages()); } @Override public int getTotalTabPages() { return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE); } @Override public int getSize() { return size; } @Override public void onViewTypeChanged(int type) { // NO OP } @Override public void onSortingTypeChanged(int type) { RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), type, getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingType = type; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSortingDirectionChanged(int direction) { RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), direction, getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), getTabPage())); this.sortingDirection = direction; BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onSearchBoxModeChanged(int searchBoxMode) { RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), searchBoxMode, getSize(), getTabSelected(), getTabPage())); this.searchBoxMode = searchBoxMode; } @Override public void onSizeChanged(int size) { RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), size, getTabSelected(), getTabPage())); this.size = size; BaseScreen.executeLater(GridScreen.class, BaseScreen::init); } @Override public void onTabSelectionChanged(int tab) { this.tabSelected = tab == tabSelected ? -1 : tab; RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), tabSelected, getTabPage())); BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } @Override public void onTabPageChanged(int page) { if (page >= 0 && page <= getTotalTabPages()) { RS.NETWORK_HANDLER.sendToServer(new PortableGridSettingsUpdateMessage(getViewType(), getSortingDirection(), getSortingType(), getSearchBoxMode(), getSize(), getTabSelected(), page)); this.tabPage = page; } } @Override public List getFilters() { return filters; } @Override public List getTabs() { return tabs; } @Override public IItemHandlerModifiable getFilter() { return filter; } @Override public ItemStorageTracker getItemStorageTracker() { if (itemStorageTracker == null) { if (player != null) { if (itemStorageTrackerId == null) { this.itemStorageTrackerId = UUID.randomUUID(); } this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) player.level()).getOrCreate(itemStorageTrackerId, StorageType.ITEM); } } return itemStorageTracker; } @Override public FluidStorageTracker getFluidStorageTracker() { if (fluidStorageTracker == null) { if (player != null) { if (fluidStorageTrackerId == null) { this.fluidStorageTrackerId = UUID.randomUUID(); } this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager((ServerLevel) player.level()).getOrCreate(fluidStorageTrackerId, StorageType.FLUID); } } return fluidStorageTracker; } @Override public CraftingContainer getCraftingMatrix() { return null; } @Override public ResultContainer getCraftingResult() { return null; } @Override public void onCraftingMatrixChanged() { // NO OP } @Override public void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { // NO OP } @Override public void onClear(Player player) { // NO OP } @Override public void onCraftedShift(Player player) { // NO OP } @Override public void onRecipeTransfer(Player player, ItemStack[][] recipe) { // NO OP } @Override public void onClosed(Player player) { if (!player.getCommandSenderWorld().isClientSide) { StackUtils.writeItems(disk, 4, stack.getTag()); } } private boolean hasDisk() { return !disk.getStackInSlot(0).isEmpty(); } @Override public boolean isGridActive() { if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && ((PortableGridBlockItem) stack.getItem()).getType() != PortableGridBlockItem.Type.CREATIVE && Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).map(IEnergyStorage::getEnergyStored).orElse(0) <= RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()) { return false; } return hasDisk(); } @Override public int getSlotId() { return slot.getSlotIdInPlayerInventory(); } @Nullable private UUID getDiskId() { return !hasDisk() ? null : ((IStorageDiskProvider) disk.getStackInSlot(0).getItem()).getId(disk.getStackInSlot(0)); } private int getStored() { API.instance().getStorageDiskSync().sendRequest(getDiskId()); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(getDiskId()); return data == null ? 0 : data.getStored(); } private int getCapacity() { API.instance().getStorageDiskSync().sendRequest(getDiskId()); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(getDiskId()); return data == null ? 0 : data.getCapacity(); } @Override public PortableGridDiskState getDiskState() { if (!hasDisk()) { return PortableGridDiskState.NONE; } if (!isGridActive()) { return PortableGridDiskState.DISCONNECTED; } int stored = getStored(); int capacity = getCapacity(); if (stored == capacity) { return PortableGridDiskState.FULL; } else if ((int) ((float) stored / (float) capacity * 100F) >= DiskState.DISK_NEAR_CAPACITY_THRESHOLD) { return PortableGridDiskState.NEAR_CAPACITY; } else { return PortableGridDiskState.NORMAL; } } @Override public AccessType getAccessType() { return AccessType.INSERT_EXTRACT; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGridBlockEntity.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid.portable; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.api.storage.cache.InvalidateCause; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskContainerContext; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableFluidGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.grid.handler.PortableItemGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableFluidStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.PortableItemStorageCache; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableFluidGridStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.storage.cache.listener.PortableItemGridStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableFluidStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.disk.PortableItemStorageDisk; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.FluidStorageTracker; import com.refinedmods.refinedstorage.apiimpl.storage.tracker.ItemStorageTracker; import com.refinedmods.refinedstorage.block.PortableGridBlock; import com.refinedmods.refinedstorage.blockentity.BaseBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IRedstoneConfigurable; import com.refinedmods.refinedstorage.blockentity.config.RedstoneMode; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationSpec; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.FilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.StorageDiskItemValidator; import com.refinedmods.refinedstorage.inventory.listener.BlockEntityInventoryListener; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.util.LevelUtils; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.inventory.ResultContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.server.ServerLifecycleHooks; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; public class PortableGridBlockEntity extends BaseBlockEntity implements IGrid, IPortableGrid, IRedstoneConfigurable, IStorageDiskContainerContext { private static final String NBT_ITEM_STORAGE_TRACKER_ID = "ItemStorageTrackerId"; private static final String NBT_FLUID_STORAGE_TRACKER_ID = "FluidStorageTrackerId"; private static final String NBT_TYPE = "Type"; private static final String NBT_ENERGY = "Energy"; private static final String NBT_ENCHANTMENTS = "Enchantments"; // @Volatile: Minecraft specific nbt key, see EnchantmentHelper public static final BlockEntitySynchronizationParameter REDSTONE_MODE = RedstoneMode.createParameter(new ResourceLocation(RS.ID, "portable_grid_redstone_mode")); private static final BlockEntitySynchronizationParameter SORTING_DIRECTION = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_sorting_direction"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSortingDirection, (t, v) -> { if (IGrid.isValidSortingDirection(v)) { t.setSortingDirection(v); t.setChanged(); } }, (initial, p) -> GridBlockEntity.trySortGrid(initial)); private static final BlockEntitySynchronizationParameter SORTING_TYPE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_sorting_type"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSortingType, (t, v) -> { if (IGrid.isValidSortingType(v)) { t.setSortingType(v); t.setChanged(); } }, (initial, p) -> GridBlockEntity.trySortGrid(initial)); private static final BlockEntitySynchronizationParameter SEARCH_BOX_MODE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_search_box_mode"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSearchBoxMode, (t, v) -> { if (IGrid.isValidSearchBoxMode(v)) { t.setSearchBoxMode(v); t.setChanged(); } }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getSearchField().setMode(p))); private static final BlockEntitySynchronizationParameter SIZE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_size"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getSize, (t, v) -> { if (IGrid.isValidSize(v)) { t.setSize(v); t.setChanged(); } }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, BaseScreen::init)); private static final BlockEntitySynchronizationParameter TAB_SELECTED = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_tab_selected"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getTabSelected, (t, v) -> { t.setTabSelected(v == t.getTabSelected() ? -1 : v); t.setChanged(); }, (initial, p) -> BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort())); private static final BlockEntitySynchronizationParameter TAB_PAGE = new BlockEntitySynchronizationParameter<>(new ResourceLocation(RS.ID, "portable_grid_tab_page"), EntityDataSerializers.INT, 0, PortableGridBlockEntity::getTabPage, (t, v) -> { if (v >= 0 && v <= t.getTotalTabPages()) { t.setTabPage(v); t.setChanged(); } }); public static BlockEntitySynchronizationSpec SPEC = BlockEntitySynchronizationSpec.builder() .addWatchedParameter(REDSTONE_MODE) .addWatchedParameter(SORTING_DIRECTION) .addWatchedParameter(SORTING_TYPE) .addWatchedParameter(SEARCH_BOX_MODE) .addWatchedParameter(SIZE) .addWatchedParameter(TAB_SELECTED) .addWatchedParameter(TAB_PAGE) .build(); private final PortableGridBlockItem.Type type; private final List filters = new ArrayList<>(); private final List tabs = new ArrayList<>(); private final FilterItemHandler filter = (FilterItemHandler) new FilterItemHandler(filters, tabs).addListener(new BlockEntityInventoryListener(this)); private final PortableItemGridHandler itemHandler = new PortableItemGridHandler(this, this); private final PortableFluidGridHandler fluidHandler = new PortableFluidGridHandler(this); private EnergyStorage energyStorage = createEnergyStorage(0); private RedstoneMode redstoneMode = RedstoneMode.IGNORE; private int sortingType; private int sortingDirection; private int searchBoxMode; private int tabSelected; private int tabPage; private int size; private GridType clientGridType; @Nullable private IStorageDisk storage; @Nullable private IStorageCache cache; private PortableGridDiskState diskState = PortableGridDiskState.NONE; private boolean active; private ItemStorageTracker itemStorageTracker; private UUID itemStorageTrackerId; private FluidStorageTracker fluidStorageTracker; private UUID fluidStorageTrackerId; private ListTag enchants = null; private boolean loadNextTick; public PortableGridBlockEntity(PortableGridBlockItem.Type type, BlockPos pos, BlockState state) { super(type == PortableGridBlockItem.Type.CREATIVE ? RSBlockEntities.CREATIVE_PORTABLE_GRID.get() : RSBlockEntities.PORTABLE_GRID.get(), pos, state, SPEC); this.type = type; } public static void serverTick(PortableGridBlockEntity blockEntity) { if (blockEntity.loadNextTick) { blockEntity.active = blockEntity.isGridActive(); blockEntity.diskState = blockEntity.getDiskState(); blockEntity.loadNextTick = false; } } private final BaseItemHandler disk = new BaseItemHandler(1) .addValidator(new StorageDiskItemValidator()) .addListener(new BlockEntityInventoryListener(this)) .addListener((handler, slot, reading) -> { if (level != null && !level.isClientSide) { loadStorage(); if (!reading) { updateState(); LevelUtils.updateBlock(level, worldPosition); // Re-send grid type } } }); private void loadStorage() { ItemStack diskStack = getDiskInventory().getStackInSlot(0); if (diskStack.isEmpty()) { this.storage = null; this.cache = null; } else { IStorageDisk diskInSlot = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(getDiskInventory().getStackInSlot(0)); if (diskInSlot != null) { StorageType diskType = ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType(); if (diskType == StorageType.ITEM) { this.storage = new PortableItemStorageDisk(diskInSlot, this); this.cache = new PortableItemStorageCache(this); } else if (diskType == StorageType.FLUID) { this.storage = new PortableFluidStorageDisk(diskInSlot, this); this.cache = new PortableFluidStorageCache(this); } this.storage.setSettings(PortableGridBlockEntity.this::updateState, PortableGridBlockEntity.this); } else { this.storage = null; this.cache = null; } } if (cache != null) { cache.invalidate(InvalidateCause.DISK_INVENTORY_CHANGED); } } @Override public void onLoad() { super.onLoad(); this.loadStorage(); loadNextTick = true; } public void applyDataFromItemToBlockEntity(ItemStack stack) { this.sortingType = WirelessGridItem.getSortingType(stack); this.sortingDirection = WirelessGridItem.getSortingDirection(stack); this.searchBoxMode = WirelessGridItem.getSearchBoxMode(stack); this.tabSelected = WirelessGridItem.getTabSelected(stack); this.tabPage = WirelessGridItem.getTabPage(stack); this.size = WirelessGridItem.getSize(stack); this.energyStorage = createEnergyStorage( Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).map(IEnergyStorage::getEnergyStored).orElse(0) ); if (stack.hasTag()) { for (int i = 0; i < 4; ++i) { StackUtils.readItems(filter, i, stack.getTag()); } StackUtils.readItems(disk, 4, stack.getTag()); this.redstoneMode = RedstoneMode.read(stack.getTag()); if (stack.getTag().contains(PortableGrid.NBT_ITEM_STORAGE_TRACKER_ID)) { itemStorageTrackerId = stack.getTag().getUUID(NBT_ITEM_STORAGE_TRACKER_ID); } if (stack.getTag().contains(PortableGrid.NBT_FLUID_STORAGE_TRACKER_ID)) { fluidStorageTrackerId = stack.getTag().getUUID(NBT_FLUID_STORAGE_TRACKER_ID); } if (stack.getTag().contains(NBT_ENCHANTMENTS)) { enchants = stack.getTag().getList(NBT_ENCHANTMENTS, Tag.TAG_COMPOUND); } } setChanged(); } public void applyDataFromBlockEntityToItem(ItemStack stack) { stack.setTag(new CompoundTag()); stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, sortingDirection); stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, sortingType); stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, searchBoxMode); stack.getTag().putInt(GridNetworkNode.NBT_SIZE, size); stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, tabSelected); stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, tabPage); if (itemStorageTrackerId != null) { stack.getTag().putUUID(PortableGrid.NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId); } if (fluidStorageTrackerId != null) { stack.getTag().putUUID(PortableGrid.NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId); } if (enchants != null) { stack.getTag().put(NBT_ENCHANTMENTS, enchants); } Optional.ofNullable(stack.getCapability(Capabilities.EnergyStorage.ITEM)).ifPresent(itemEnergy -> itemEnergy.receiveEnergy(energyStorage.getEnergyStored(), false)); for (int i = 0; i < 4; ++i) { StackUtils.writeItems(filter, i, stack.getTag()); } StackUtils.writeItems(disk, 4, stack.getTag()); redstoneMode.write(stack.getTag()); } private EnergyStorage createEnergyStorage(int energyStored) { return new EnergyStorage( RS.SERVER_CONFIG.getPortableGrid().getCapacity(), RS.SERVER_CONFIG.getPortableGrid().getCapacity(), RS.SERVER_CONFIG.getPortableGrid().getCapacity(), energyStored ); } @Override public GridType getGridType() { return clientGridType != null ? clientGridType : getServerGridType(); } private GridType getServerGridType() { return (getDiskInventory().getStackInSlot(0).isEmpty() || ((IStorageDiskProvider) getDiskInventory().getStackInSlot(0).getItem()).getType() == StorageType.ITEM) ? GridType.NORMAL : GridType.FLUID; } @Nullable @Override public IStorageCache getStorageCache() { return storage != null ? cache : null; } @Override public IStorageCacheListener createListener(ServerPlayer player) { return getServerGridType() == GridType.FLUID ? new PortableFluidGridStorageCacheListener(this, player) : new PortableItemGridStorageCacheListener(this, player); } @Nullable @Override public IItemGridHandler getItemHandler() { return itemHandler; } @Nullable @Override public IFluidGridHandler getFluidHandler() { return fluidHandler; } @Override public void addCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public void removeCraftingListener(ICraftingGridListener listener) { // NO OP } @Override public Component getTitle() { return Component.translatable("gui.refinedstorage.portable_grid"); } @Override public int getViewType() { return -1; } @Override public int getSortingType() { return level.isClientSide ? SORTING_TYPE.getValue() : sortingType; } public void setSortingType(int sortingType) { this.sortingType = sortingType; } @Override public int getSortingDirection() { return level.isClientSide ? SORTING_DIRECTION.getValue() : sortingDirection; } public void setSortingDirection(int sortingDirection) { this.sortingDirection = sortingDirection; } @Override public int getSearchBoxMode() { return level.isClientSide ? SEARCH_BOX_MODE.getValue() : searchBoxMode; } public void setSearchBoxMode(int searchBoxMode) { this.searchBoxMode = searchBoxMode; } @Override public int getTabSelected() { return level.isClientSide ? TAB_SELECTED.getValue() : tabSelected; } public void setTabSelected(int tabSelected) { this.tabSelected = tabSelected; } @Override public int getTabPage() { return level.isClientSide ? TAB_PAGE.getValue() : Math.min(tabPage, getTotalTabPages()); } public void setTabPage(int page) { this.tabPage = page; } @Override public int getTotalTabPages() { return (int) Math.floor((float) Math.max(0, tabs.size() - 1) / (float) IGrid.TABS_PER_PAGE); } @Override public int getSize() { return level.isClientSide ? SIZE.getValue() : size; } public void setSize(int size) { this.size = size; } @Override public void onViewTypeChanged(int type) { // NO OP } @Override public void onSortingTypeChanged(int type) { BlockEntitySynchronizationManager.setParameter(SORTING_TYPE, type); } @Override public void onSortingDirectionChanged(int direction) { BlockEntitySynchronizationManager.setParameter(SORTING_DIRECTION, direction); } @Override public void onSearchBoxModeChanged(int searchBoxMode) { BlockEntitySynchronizationManager.setParameter(SEARCH_BOX_MODE, searchBoxMode); } @Override public void onSizeChanged(int size) { BlockEntitySynchronizationManager.setParameter(SIZE, size); } @Override public void onTabSelectionChanged(int tab) { BlockEntitySynchronizationManager.setParameter(TAB_SELECTED, tab); } @Override public void onTabPageChanged(int page) { if (page >= 0 && page <= getTotalTabPages()) { BlockEntitySynchronizationManager.setParameter(PortableGridBlockEntity.TAB_PAGE, page); } } @Override public List getFilters() { return filters; } @Override public List getTabs() { return tabs; } @Override public IItemHandlerModifiable getFilter() { return filter; } @Override public IStorageTracker getItemStorageTracker() { if (itemStorageTracker == null) { if (itemStorageTrackerId == null) { this.itemStorageTrackerId = UUID.randomUUID(); } this.itemStorageTracker = (ItemStorageTracker) API.instance().getStorageTrackerManager(ServerLifecycleHooks.getCurrentServer().overworld()).getOrCreate(itemStorageTrackerId, StorageType.ITEM); } return itemStorageTracker; } @Override public IStorageTracker getFluidStorageTracker() { if (fluidStorageTracker == null) { if (fluidStorageTrackerId == null) { this.fluidStorageTrackerId = UUID.randomUUID(); } this.fluidStorageTracker = (FluidStorageTracker) API.instance().getStorageTrackerManager(ServerLifecycleHooks.getCurrentServer().overworld()).getOrCreate(fluidStorageTrackerId, StorageType.FLUID); } return fluidStorageTracker; } @Override public CraftingContainer getCraftingMatrix() { return null; } @Override public ResultContainer getCraftingResult() { return null; } @Override public void onCraftingMatrixChanged() { // NO OP } @Override public void onCrafted(Player player, @Nullable IStackList availableItems, @Nullable IStackList usedItems) { // NO OP } @Override public void onClear(Player player) { // NO OP } @Override public void onCraftedShift(Player player) { // NO OP } @Override public void onRecipeTransfer(Player player, ItemStack[][] recipe) { // NO OP } @Override public void onClosed(Player player) { // NO OP } private boolean hasDisk() { return !disk.getStackInSlot(0).isEmpty(); } @Override public boolean isGridActive() { if (level.isClientSide) { BlockState state = level.getBlockState(worldPosition); if (state.getBlock() instanceof PortableGridBlock) { return state.getValue(PortableGridBlock.ACTIVE); } return false; } if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && type != PortableGridBlockItem.Type.CREATIVE && energyStorage.getEnergyStored() <= RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()) { return false; } if (!hasDisk()) { return false; } return redstoneMode.isEnabled(level.hasNeighborSignal(worldPosition)); } @Override public int getSlotId() { return -1; } @Override @Nullable public IStorageCache getCache() { return cache; } @Override @Nullable public IStorageDisk getStorage() { return storage; } @Override public void drainEnergy(int energy) { if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && type != PortableGridBlockItem.Type.CREATIVE && redstoneMode.isEnabled(level.hasNeighborSignal(worldPosition))) { energyStorage.extractEnergy(energy, false); updateState(); } } @Override public int getEnergy() { if (RS.SERVER_CONFIG.getPortableGrid().getUseEnergy() && type != PortableGridBlockItem.Type.CREATIVE) { return energyStorage.getEnergyStored(); } return RS.SERVER_CONFIG.getPortableGrid().getCapacity(); } public EnergyStorage getEnergyStorage() { return energyStorage; } @Override public PortableGridDiskState getDiskState() { if (!hasDisk()) { return PortableGridDiskState.NONE; } if (!isGridActive()) { return PortableGridDiskState.DISCONNECTED; } int stored = storage != null ? storage.getStored() : 0; int capacity = storage != null ? storage.getCapacity() : 0; if (stored == capacity) { return PortableGridDiskState.FULL; } else if ((int) ((float) stored / (float) capacity * 100F) >= DiskState.DISK_NEAR_CAPACITY_THRESHOLD) { return PortableGridDiskState.NEAR_CAPACITY; } else { return PortableGridDiskState.NORMAL; } } public void updateState() { PortableGridDiskState newDiskState = getDiskState(); if (this.diskState != newDiskState) { this.diskState = newDiskState; level.setBlockAndUpdate(worldPosition, level.getBlockState(worldPosition).setValue(PortableGridBlock.DISK_STATE, diskState)); } boolean isActive = isGridActive(); if (this.active != isActive) { this.active = isActive; level.setBlockAndUpdate(worldPosition, level.getBlockState(worldPosition).setValue(PortableGridBlock.ACTIVE, active)); } } @Override public BaseItemHandler getDiskInventory() { return disk; } @Override public void saveAdditional(CompoundTag tag) { super.saveAdditional(tag); tag.putInt(GridNetworkNode.NBT_SORTING_DIRECTION, sortingDirection); tag.putInt(GridNetworkNode.NBT_SORTING_TYPE, sortingType); tag.putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, searchBoxMode); tag.putInt(GridNetworkNode.NBT_SIZE, size); tag.putInt(GridNetworkNode.NBT_TAB_SELECTED, tabSelected); tag.putInt(GridNetworkNode.NBT_TAB_PAGE, tabPage); StackUtils.writeItems(disk, 0, tag); StackUtils.writeItems(filter, 1, tag); tag.putInt(NBT_ENERGY, energyStorage.getEnergyStored()); redstoneMode.write(tag); if (itemStorageTrackerId != null) { tag.putUUID(NBT_ITEM_STORAGE_TRACKER_ID, itemStorageTrackerId); } if (fluidStorageTrackerId != null) { tag.putUUID(NBT_FLUID_STORAGE_TRACKER_ID, fluidStorageTrackerId); } if (enchants != null) { tag.put(NBT_ENCHANTMENTS, enchants); } } @Override public void load(CompoundTag tag) { super.load(tag); if (tag.contains(GridNetworkNode.NBT_SORTING_DIRECTION)) { sortingDirection = tag.getInt(GridNetworkNode.NBT_SORTING_DIRECTION); } if (tag.contains(GridNetworkNode.NBT_SORTING_TYPE)) { sortingType = tag.getInt(GridNetworkNode.NBT_SORTING_TYPE); } if (tag.contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) { searchBoxMode = tag.getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE); } if (tag.contains(GridNetworkNode.NBT_SIZE)) { size = tag.getInt(GridNetworkNode.NBT_SIZE); } if (tag.contains(GridNetworkNode.NBT_TAB_SELECTED)) { tabSelected = tag.getInt(GridNetworkNode.NBT_TAB_SELECTED); } if (tag.contains(GridNetworkNode.NBT_TAB_PAGE)) { tabPage = tag.getInt(GridNetworkNode.NBT_TAB_PAGE); } StackUtils.readItems(disk, 0, tag); StackUtils.readItems(filter, 1, tag); if (tag.contains(NBT_ENERGY)) { energyStorage = createEnergyStorage(tag.getInt(NBT_ENERGY)); } redstoneMode = RedstoneMode.read(tag); if (tag.contains(NBT_ITEM_STORAGE_TRACKER_ID)) { itemStorageTrackerId = tag.getUUID(NBT_ITEM_STORAGE_TRACKER_ID); } if (tag.contains(NBT_FLUID_STORAGE_TRACKER_ID)) { fluidStorageTrackerId = tag.getUUID(NBT_FLUID_STORAGE_TRACKER_ID); } if (tag.contains(NBT_ENCHANTMENTS)) { enchants = tag.getList(NBT_ENCHANTMENTS, Tag.TAG_COMPOUND); } } @Override public CompoundTag writeUpdate(CompoundTag tag) { tag.putInt(NBT_TYPE, getServerGridType().ordinal()); return super.writeUpdate(tag); } @Override public void readUpdate(CompoundTag tag) { super.readUpdate(tag); clientGridType = GridType.values()[tag.getInt(NBT_TYPE)]; } public void onOpened() { drainEnergy(RS.SERVER_CONFIG.getPortableGrid().getOpenUsage()); } @Override public RedstoneMode getRedstoneMode() { return redstoneMode; } @Override public void setRedstoneMode(RedstoneMode mode) { this.redstoneMode = mode; setChanged(); } @Override public AccessType getAccessType() { return AccessType.INSERT_EXTRACT; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/blockentity/grid/portable/PortableGridDiskState.java ================================================ package com.refinedmods.refinedstorage.blockentity.grid.portable; import net.minecraft.util.StringRepresentable; public enum PortableGridDiskState implements StringRepresentable { NORMAL(0, "normal"), NEAR_CAPACITY(1, "near_capacity"), FULL(2, "full"), DISCONNECTED(3, "disconnected"), NONE(4, "none"); private final int id; private final String type; PortableGridDiskState(int id, String type) { this.id = id; this.type = type; } public int getId() { return id; } @Override public String getSerializedName() { return type; } @Override public String toString() { return type; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/disk/CreateDiskCommand.java ================================================ package com.refinedmods.refinedstorage.command.disk; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.UuidArgument; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import java.util.UUID; public class CreateDiskCommand implements Command { public static ArgumentBuilder register() { return Commands.literal("create") .requires(cs -> cs.hasPermission(2)) .then(Commands.argument("player", EntityArgument.player()) .then(Commands.argument("id", UuidArgument.uuid()).suggests(new StorageDiskIdSuggestionProvider()) .executes(new CreateDiskCommand()) ) ); } @Override public int run(CommandContext context) throws CommandSyntaxException { Player player = EntityArgument.getPlayer(context, "player"); UUID id = UuidArgument.getUuid(context, "id"); IStorageDisk disk = API.instance().getStorageDiskManager(context.getSource().getLevel()).get(id); if (disk == null) { context.getSource().sendFailure(Component.translatable("commands.refinedstorage.disk.create.error.disk_not_found", id)); } else { IStorageDiskFactory factory = API.instance().getStorageDiskRegistry().get(disk.getFactoryId()); if (factory != null) { ItemStack stack = factory.createDiskItem(disk, id); // @Volatile: From GiveCommand boolean flag = player.getInventory().add(stack); if (flag && stack.isEmpty()) { stack.setCount(1); ItemEntity itemEntity = player.drop(stack, false); if (itemEntity != null) { itemEntity.makeFakeItem(); } 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); player.containerMenu.broadcastChanges(); } else { ItemEntity itemEntity = player.drop(stack, false); if (itemEntity != null) { itemEntity.setNoPickUpDelay(); itemEntity.setThrower(player); } } context.getSource().sendSuccess(() -> Component.translatable( "commands.refinedstorage.disk.create.success", Component.literal(id.toString()).setStyle(Styles.YELLOW), context.getSource().getDisplayName().copy().setStyle(Styles.YELLOW) ), false); } } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/disk/ListDiskCommand.java ================================================ package com.refinedmods.refinedstorage.command.disk; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; public class ListDiskCommand implements Command { public static ArgumentBuilder register() { return Commands.literal("list") .requires(cs -> cs.hasPermission(2)) .executes(new ListDiskCommand()) .then(ListDiskForPlayerCommand.register()); } @Override public int run(CommandContext context) { API.instance().getStorageDiskManager(context.getSource().getLevel()) .getAll() .keySet() .forEach(id -> context.getSource().sendSuccess(() -> Component.literal(id.toString()), false)); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/disk/ListDiskForPlayerCommand.java ================================================ package com.refinedmods.refinedstorage.command.disk; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import java.util.Map; public class ListDiskForPlayerCommand implements Command { public static ArgumentBuilder register() { return Commands.argument("player", EntityArgument.player()).executes(new ListDiskForPlayerCommand()); } @Override public int run(CommandContext context) throws CommandSyntaxException { Player player = EntityArgument.getPlayer(context, "player"); API.instance().getStorageDiskManager(context.getSource().getLevel()) .getAll() .entrySet() .stream() .filter(entry -> player.getGameProfile().getId().equals(entry.getValue().getOwner())) .map(Map.Entry::getKey) .forEach(id -> context.getSource().sendSuccess(() -> Component.literal(id.toString()), false)); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/disk/StorageDiskIdSuggestionProvider.java ================================================ package com.refinedmods.refinedstorage.command.disk; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import java.util.concurrent.CompletableFuture; public class StorageDiskIdSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { API.instance().getStorageDiskManager(context.getSource().getLevel()) .getAll() .keySet() .forEach(id -> builder.suggest(id.toString())); return builder.buildFuture(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/GetNetworkCommand.java ================================================ package com.refinedmods.refinedstorage.command.network; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.command.network.autocrafting.CancelAllAutocraftingCommand; import com.refinedmods.refinedstorage.command.network.autocrafting.GetAutocraftingCommand; import com.refinedmods.refinedstorage.command.network.autocrafting.ListAutocraftingCommand; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; public class GetNetworkCommand extends NetworkCommand { public static ArgumentBuilder register() { return Commands.literal("get") .requires(cs -> cs.hasPermission(2)) .then(Commands.argument("dimension", DimensionArgument.dimension()) .then(Commands.argument("pos", BlockPosArgument.blockPos()).suggests(new NetworkPositionSuggestionProvider()) .executes(new GetNetworkCommand()) .then(Commands.literal("autocrafting") .then(ListAutocraftingCommand.register()) .then(GetAutocraftingCommand.register()) .then(CancelAllAutocraftingCommand.register()) ))); } @Override protected int run(CommandContext context, INetwork network) { ListNetworkCommand.sendInfo(context, new ListNetworkCommand.NetworkInList(network), true); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/ListNetworkCommand.java ================================================ package com.refinedmods.refinedstorage.command.network; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import java.text.DecimalFormat; import java.util.Comparator; public class ListNetworkCommand implements Command { private static final DecimalFormat TIME_FORMATTER = new DecimalFormat("########0.000"); public static ArgumentBuilder register() { return Commands.literal("list") .requires(cs -> cs.hasPermission(2)) .then(Commands.argument("dimension", DimensionArgument.dimension()) .executes(new ListNetworkCommand())); } public static void sendInfo(CommandContext context, NetworkInList listItem, boolean detailed) { context.getSource().sendSuccess(() -> Component.translatable( "commands.refinedstorage.network.list.pos", listItem.network.getPosition().getX(), listItem.network.getPosition().getY(), listItem.network.getPosition().getZ() ) .append(" [") .append(Component.translatable( "commands.refinedstorage.network.list.tick_times", Component.literal(TIME_FORMATTER.format(listItem.tickTime)).setStyle(Styles.YELLOW), Component.literal(TIME_FORMATTER.format(listItem.tps)).setStyle(Styles.YELLOW) )) .append("]"), false); if (detailed) { context.getSource().sendSuccess(() -> Component.translatable("commands.refinedstorage.network.list.autocrafting_tasks", Component.literal(listItem.network.getCraftingManager().getTasks().size() + "").setStyle(Styles.YELLOW) ), false); context.getSource().sendSuccess(() -> Component.translatable("commands.refinedstorage.network.list.nodes", Component.literal(listItem.network.getNodeGraph().all().size() + "").setStyle(Styles.YELLOW) ), false); context.getSource().sendSuccess(() -> Component.translatable("commands.refinedstorage.network.list.energy_usage", Component.literal(listItem.network.getEnergyUsage() + "").setStyle(Styles.YELLOW) ), false); } } @Override public int run(CommandContext context) throws CommandSyntaxException { ServerLevel level = DimensionArgument.getDimension(context, "dimension"); API.instance().getNetworkManager(level) .all() .stream() .map(NetworkInList::new) .sorted(Comparator.comparingDouble(network -> network.tickTime)) .forEach(listItem -> sendInfo(context, listItem, false)); return 0; } public static class NetworkInList { private final double tickTime; private final double tps; private final INetwork network; public NetworkInList(INetwork network) { this.network = network; // @Volatile: From TPSCommand this.tickTime = mean(network.getTickTimes()) * 1.0E-6D; this.tps = Math.min(1000.0 / tickTime, 20); } private long mean(long[] values) { long sum = 0L; for (long v : values) { sum += v; } return sum / values.length; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/NetworkCommand.java ================================================ package com.refinedmods.refinedstorage.command.network; import com.mojang.brigadier.Command; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; public abstract class NetworkCommand implements Command { @Override public int run(CommandContext context) throws CommandSyntaxException { ServerLevel level = DimensionArgument.getDimension(context, "dimension"); BlockPos pos = BlockPosArgument.getLoadedBlockPos(context, "pos"); INetwork network = API.instance().getNetworkManager(level).getNetwork(pos); if (network == null) { context.getSource().sendFailure(Component.translatable("commands.refinedstorage.network.get.error.not_found")); return 0; } else { return run(context, network); } } protected abstract int run(CommandContext context, INetwork network) throws CommandSyntaxException; } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/NetworkPositionSuggestionProvider.java ================================================ package com.refinedmods.refinedstorage.command.network; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.server.level.ServerLevel; import java.util.concurrent.CompletableFuture; public class NetworkPositionSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { ServerLevel level = DimensionArgument.getDimension(context, "dimension"); API.instance().getNetworkManager(level).all().forEach(network -> builder.suggest(network.getPosition().getX() + " " + network.getPosition().getY() + " " + network.getPosition().getZ())); return builder.buildFuture(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/AutocraftingIdSuggestionProvider.java ================================================ package com.refinedmods.refinedstorage.command.network.autocrafting; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.SuggestionProvider; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.arguments.DimensionArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerLevel; import java.util.concurrent.CompletableFuture; public class AutocraftingIdSuggestionProvider implements SuggestionProvider { @Override public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) throws CommandSyntaxException { ServerLevel level = DimensionArgument.getDimension(context, "dimension"); BlockPos pos = BlockPosArgument.getLoadedBlockPos(context, "pos"); INetwork network = API.instance().getNetworkManager(level).getNetwork(pos); if (network != null) { network.getCraftingManager().getTasks().forEach(task -> builder.suggest(task.getId().toString())); } return builder.buildFuture(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/CancelAllAutocraftingCommand.java ================================================ package com.refinedmods.refinedstorage.command.network.autocrafting; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.command.network.NetworkCommand; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; public class CancelAllAutocraftingCommand extends NetworkCommand { public static ArgumentBuilder register() { return Commands.literal("cancel") .executes(new CancelAllAutocraftingCommand()) .then(CancelSingleAutocraftingCommand.register()); } public static void sendCancelMessage(CommandContext context, int count) { final String translationKey = count == 1 ? "commands.refinedstorage.network.autocrafting.cancel.single" : "commands.refinedstorage.network.autocrafting.cancel.multiple"; context.getSource().sendSuccess(() -> Component.translatable(translationKey, Component.literal(String.valueOf(count)).setStyle(Styles.YELLOW)), false); } @Override protected int run(CommandContext context, INetwork network) { int count = network.getCraftingManager().getTasks().size(); network.getCraftingManager().getTasks().forEach(task -> network.getCraftingManager().cancel(task.getId())); sendCancelMessage(context, count); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/CancelSingleAutocraftingCommand.java ================================================ package com.refinedmods.refinedstorage.command.network.autocrafting; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.command.network.NetworkCommand; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.UuidArgument; import java.util.UUID; public class CancelSingleAutocraftingCommand extends NetworkCommand { public static ArgumentBuilder register() { return Commands.argument("id", UuidArgument.uuid()).suggests(new AutocraftingIdSuggestionProvider()) .executes(new CancelSingleAutocraftingCommand()); } @Override protected int run(CommandContext context, INetwork network) { UUID id = UuidArgument.getUuid(context, "id"); int count = 0; ICraftingTask task = network.getCraftingManager().getTask(id); if (task != null) { count = 1; network.getCraftingManager().cancel(task.getId()); } CancelAllAutocraftingCommand.sendCancelMessage(context, count); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/GetAutocraftingCommand.java ================================================ package com.refinedmods.refinedstorage.command.network.autocrafting; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.command.network.NetworkCommand; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.UuidArgument; import net.minecraft.network.chat.Component; import java.util.UUID; public class GetAutocraftingCommand extends NetworkCommand { public static ArgumentBuilder register() { return Commands.literal("get").then( Commands.argument("id", UuidArgument.uuid()).suggests(new AutocraftingIdSuggestionProvider()) .executes(new GetAutocraftingCommand()) ); } @Override protected int run(CommandContext context, INetwork network) { UUID id = UuidArgument.getUuid(context, "id"); ICraftingTask task = network.getCraftingManager().getTask(id); if (task == null) { context.getSource().sendFailure(Component.translatable("commands.refinedstorage.network.autocrafting.get.error.not_found")); } else { ListAutocraftingCommand.addInfo(context, task); } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/network/autocrafting/ListAutocraftingCommand.java ================================================ package com.refinedmods.refinedstorage.command.network.autocrafting; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.command.network.NetworkCommand; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; public class ListAutocraftingCommand extends NetworkCommand { public static ArgumentBuilder register() { return Commands.literal("list").executes(new ListAutocraftingCommand()); } public static void addInfo(CommandContext context, ICraftingTask task) { context.getSource().sendSuccess(() -> Component.literal(getAmount(task.getRequested()) + "x ") .append(getName(task.getRequested()).copy().setStyle(Styles.YELLOW)) .append(" ") .append("(" + task.getCompletionPercentage() + "%)") .append(" ") .append(Component.literal("[" + task.getId().toString() + "]").setStyle(Styles.GRAY)), false ); } private static int getAmount(ICraftingRequestInfo info) { if (info.getItem() != null) { return info.getItem().getCount(); } if (info.getFluid() != null) { return info.getFluid().getAmount(); } return 0; } private static Component getName(ICraftingRequestInfo info) { if (info.getItem() != null) { return info.getItem().getHoverName(); } if (info.getFluid() != null) { return info.getFluid().getDisplayName(); } return Component.empty(); } @Override protected int run(CommandContext context, INetwork network) { network.getCraftingManager().getTasks().forEach(task -> addInfo(context, task)); return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/command/pattern/PatternDumpCommand.java ================================================ package com.refinedmods.refinedstorage.command.pattern; import com.mojang.brigadier.Command; import com.mojang.brigadier.builder.ArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class PatternDumpCommand implements Command { public static ArgumentBuilder register() { return Commands.literal("dump") .executes(new PatternDumpCommand()); } @Override public int run(CommandContext context) throws CommandSyntaxException { ItemStack stack = context.getSource().getPlayerOrException().getInventory().getSelected(); if (stack.getItem() instanceof PatternItem) { boolean processing = PatternItem.isProcessing(stack); boolean exact = PatternItem.isExact(stack); AllowedTagList allowedTagList = PatternItem.getAllowedTags(stack); ICraftingPattern pattern = PatternItem.fromCache(context.getSource().getLevel(), stack); context.getSource().sendSuccess(() -> Component.literal("Crafting task factory ID: ").setStyle(Styles.YELLOW).append(Component.literal(pattern.getCraftingTaskFactoryId().toString()).setStyle(Styles.WHITE)), false); if (!pattern.isValid()) { context.getSource().sendFailure(Component.literal("Pattern is invalid! Reason: ").append(pattern.getErrorMessage())); } else { context.getSource().sendSuccess(() -> Component.literal("Processing: ").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(processing)).setStyle(Styles.WHITE)), false); context.getSource().sendSuccess(() -> Component.literal("Exact: ").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(exact)).setStyle(Styles.WHITE)), false); context.getSource().sendSuccess(() -> Component.literal("Has allowed tag list: ").setStyle(Styles.YELLOW).append(Component.literal(String.valueOf(allowedTagList != null)).setStyle(Styles.WHITE)), false); if (pattern.isProcessing()) { for (int i = 0; i < pattern.getInputs().size(); ++i) { final int ii = i; if (!pattern.getInputs().get(i).isEmpty()) { context.getSource().sendSuccess(() -> Component.literal("Item inputs in slot " + ii + ":").setStyle(Styles.YELLOW), false); for (int j = 0; j < pattern.getInputs().get(i).size(); ++j) { final int jj = j; context.getSource().sendSuccess(() -> Component.literal("- Possibility #" + jj + ": " + pattern.getInputs().get(ii).get(jj).getCount() + "x ").append(pattern.getInputs().get(ii).get(jj).getHoverName()), false); } } if (allowedTagList != null) { for (ResourceLocation allowed : allowedTagList.getAllowedItemTags().get(i)) { context.getSource().sendSuccess(() -> Component.literal("- Allowed item tag: " + allowed.toString()), false); } } } for (int i = 0; i < pattern.getFluidInputs().size(); ++i) { final int ii = i; if (!pattern.getFluidInputs().get(i).isEmpty()) { context.getSource().sendSuccess(() -> Component.literal("Fluid inputs in slot " + ii + ":").setStyle(Styles.YELLOW), false); for (int j = 0; j < pattern.getFluidInputs().get(i).size(); ++j) { final int jj = j; context.getSource().sendSuccess(() -> Component.literal("- Possibility #" + jj + ": " + pattern.getFluidInputs().get(ii).get(jj).getAmount() + " mB ").append(pattern.getFluidInputs().get(ii).get(jj).getDisplayName()), false); } } if (allowedTagList != null) { for (ResourceLocation allowed : allowedTagList.getAllowedFluidTags().get(i)) { context.getSource().sendSuccess(() -> Component.literal("- Allowed fluid tag: " + allowed.toString()), false); } } } context.getSource().sendSuccess(() -> Component.literal("Outputs").setStyle(Styles.YELLOW), false); for (ItemStack output : pattern.getOutputs()) { context.getSource().sendSuccess(() -> Component.literal("- " + output.getCount() + "x ").append(output.getHoverName()), false); } context.getSource().sendSuccess(() -> Component.literal("Fluid outputs").setStyle(Styles.YELLOW), false); for (FluidStack output : pattern.getFluidOutputs()) { context.getSource().sendSuccess(() -> Component.literal("- " + output.getAmount() + " mB ").append(output.getDisplayName()), false); } } else { for (int i = 0; i < pattern.getInputs().size(); ++i) { final int ii = i; if (!pattern.getInputs().get(i).isEmpty()) { context.getSource().sendSuccess(() -> Component.literal("Inputs in slot " + ii + ":").setStyle(Styles.YELLOW), false); for (int j = 0; j < pattern.getInputs().get(i).size(); ++j) { final int jj = j; context.getSource().sendSuccess(() -> Component.literal("- Possibility #" + jj + ": " + pattern.getInputs().get(ii).get(jj).getCount() + "x ").append(pattern.getInputs().get(ii).get(jj).getHoverName()), false); } } } context.getSource().sendSuccess(() -> Component.literal("Outputs").setStyle(Styles.YELLOW), false); for (ItemStack output : pattern.getOutputs()) { context.getSource().sendSuccess(() -> Component.literal("- " + output.getCount() + "x ").append(output.getHoverName()), false); } boolean anyByproducts = false; for (ItemStack byproduct : pattern.getByproducts()) { if (!byproduct.isEmpty()) { if (!anyByproducts) { context.getSource().sendSuccess(() -> Component.literal("Byproducts").setStyle(Styles.YELLOW), false); anyByproducts = true; } context.getSource().sendSuccess(() -> Component.literal("- " + byproduct.getCount() + "x ").append(byproduct.getHoverName()), false); } } } } } else { context.getSource().sendFailure(Component.literal("You need to be holding a pattern in your hand.")); } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/config/ClientConfig.java ================================================ package com.refinedmods.refinedstorage.config; import net.neoforged.neoforge.common.ModConfigSpec; public class ClientConfig { private final ModConfigSpec.Builder builder = new ModConfigSpec.Builder(); private final ModConfigSpec spec; private final Grid grid; private final CrafterManager crafterManager; private final Cover cover; public ClientConfig() { grid = new Grid(); crafterManager = new CrafterManager(); cover = new Cover(); spec = builder.build(); } public ModConfigSpec getSpec() { return spec; } public Grid getGrid() { return grid; } public CrafterManager getCrafterManager() { return crafterManager; } public Cover getCover() { return cover; } public class Grid { private final ModConfigSpec.IntValue maxRowsStretch; private final ModConfigSpec.BooleanValue detailedTooltip; private final ModConfigSpec.BooleanValue largeFont; private final ModConfigSpec.BooleanValue preventSortingWhileShiftIsDown; private final ModConfigSpec.BooleanValue rememberSearchQuery; public Grid() { builder.push("grid"); maxRowsStretch = builder.comment("The maximum amount of rows that the Grid can show when stretched") .defineInRange("maxRowsStretch", Integer.MAX_VALUE, 3, Integer.MAX_VALUE); detailedTooltip = builder.comment( "Whether the Grid should display a detailed tooltip when hovering over an item or fluid") .define("detailedTooltip", true); largeFont = builder.comment("Whether the Grid should use a large font for stack quantity display") .define("largeFont", false); preventSortingWhileShiftIsDown = builder.comment("Whether the Grid should prevent sorting while the shift key is held down") .define("preventSortingWhileShiftIsDown", true); rememberSearchQuery = builder.comment( "Whether the Grid should remember the search query when closing and re-opening the Grid") .define("rememberSearchQuery", false); builder.pop(); } public int getMaxRowsStretch() { return maxRowsStretch.get(); } public boolean getDetailedTooltip() { return detailedTooltip.get(); } public boolean getLargeFont() { return largeFont.get(); } public boolean getPreventSortingWhileShiftIsDown() { return preventSortingWhileShiftIsDown.get(); } public boolean getRememberSearchQuery() { return rememberSearchQuery.get(); } } public class CrafterManager { private final ModConfigSpec.IntValue maxRowsStretch; public CrafterManager() { builder.push("crafterManager"); maxRowsStretch = builder.comment("The maximum amount of rows that the Crafter Manager can show when stretched") .defineInRange("maxRowsStretch", Integer.MAX_VALUE, 3, Integer.MAX_VALUE); builder.pop(); } public int getMaxRowsStretch() { return maxRowsStretch.get(); } } public class Cover { private final ModConfigSpec.BooleanValue showAllCoversInJEI; public Cover() { builder.push("cover"); showAllCoversInJEI = builder.comment("When true all the possible covers will be added to JEI (Game restart required)") .define("showAllCoversInJEI", false); builder.pop(); } public boolean showAllRecipesInJEI() { return showAllCoversInJEI.get(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/config/ServerConfig.java ================================================ package com.refinedmods.refinedstorage.config; import net.neoforged.neoforge.common.ModConfigSpec; public class ServerConfig { private final ModConfigSpec.Builder builder = new ModConfigSpec.Builder(); private final ModConfigSpec spec; private final Upgrades upgrades; private final Controller controller; private final Cable cable; private final Grid grid; private final DiskDrive diskDrive; private final StorageBlock storageBlock; private final FluidStorageBlock fluidStorageBlock; private final ExternalStorage externalStorage; private final Importer importer; private final Exporter exporter; private final NetworkReceiver networkReceiver; private final NetworkTransmitter networkTransmitter; private final Relay relay; private final Detector detector; private final SecurityManager securityManager; private final Interface iface; private final FluidInterface fluidInterface; private final WirelessTransmitter wirelessTransmitter; private final StorageMonitor storageMonitor; private final WirelessGrid wirelessGrid; private final WirelessFluidGrid wirelessFluidGrid; private final Constructor constructor; private final Destructor destructor; private final DiskManipulator diskManipulator; private final PortableGrid portableGrid; private final Crafter crafter; private final CrafterManager crafterManager; private final CraftingMonitor craftingMonitor; private final WirelessCraftingMonitor wirelessCraftingMonitor; private final Autocrafting autocrafting; public ServerConfig() { upgrades = new Upgrades(); controller = new Controller(); cable = new Cable(); grid = new Grid(); diskDrive = new DiskDrive(); storageBlock = new StorageBlock(); fluidStorageBlock = new FluidStorageBlock(); externalStorage = new ExternalStorage(); importer = new Importer(); exporter = new Exporter(); networkReceiver = new NetworkReceiver(); networkTransmitter = new NetworkTransmitter(); relay = new Relay(); detector = new Detector(); securityManager = new SecurityManager(); iface = new Interface(); fluidInterface = new FluidInterface(); wirelessTransmitter = new WirelessTransmitter(); storageMonitor = new StorageMonitor(); wirelessGrid = new WirelessGrid(); wirelessFluidGrid = new WirelessFluidGrid(); constructor = new Constructor(); destructor = new Destructor(); diskManipulator = new DiskManipulator(); portableGrid = new PortableGrid(); crafter = new Crafter(); crafterManager = new CrafterManager(); craftingMonitor = new CraftingMonitor(); wirelessCraftingMonitor = new WirelessCraftingMonitor(); autocrafting = new Autocrafting(); spec = builder.build(); } public ModConfigSpec getSpec() { return spec; } public Upgrades getUpgrades() { return upgrades; } public Controller getController() { return controller; } public Cable getCable() { return cable; } public DiskDrive getDiskDrive() { return diskDrive; } public Grid getGrid() { return grid; } public StorageBlock getStorageBlock() { return storageBlock; } public FluidStorageBlock getFluidStorageBlock() { return fluidStorageBlock; } public ExternalStorage getExternalStorage() { return externalStorage; } public Importer getImporter() { return importer; } public Exporter getExporter() { return exporter; } public NetworkReceiver getNetworkReceiver() { return networkReceiver; } public NetworkTransmitter getNetworkTransmitter() { return networkTransmitter; } public Relay getRelay() { return relay; } public Detector getDetector() { return detector; } public SecurityManager getSecurityManager() { return securityManager; } public Interface getInterface() { return iface; } public FluidInterface getFluidInterface() { return fluidInterface; } public WirelessTransmitter getWirelessTransmitter() { return wirelessTransmitter; } public StorageMonitor getStorageMonitor() { return storageMonitor; } public WirelessGrid getWirelessGrid() { return wirelessGrid; } public WirelessFluidGrid getWirelessFluidGrid() { return wirelessFluidGrid; } public Constructor getConstructor() { return constructor; } public Destructor getDestructor() { return destructor; } public DiskManipulator getDiskManipulator() { return diskManipulator; } public PortableGrid getPortableGrid() { return portableGrid; } public Crafter getCrafter() { return crafter; } public CrafterManager getCrafterManager() { return crafterManager; } public CraftingMonitor getCraftingMonitor() { return craftingMonitor; } public WirelessCraftingMonitor getWirelessCraftingMonitor() { return wirelessCraftingMonitor; } public Autocrafting getAutocrafting() { return autocrafting; } public class Controller { private final ModConfigSpec.BooleanValue useEnergy; private final ModConfigSpec.IntValue capacity; private final ModConfigSpec.IntValue baseUsage; private final ModConfigSpec.IntValue maxTransfer; public Controller() { builder.push("controller"); useEnergy = builder.comment("Whether the Controller uses energy").define("useEnergy", true); capacity = builder.comment("The energy capacity of the Controller") .defineInRange("capacity", 32000, 0, Integer.MAX_VALUE); baseUsage = builder.comment("The base energy used by the Controller") .defineInRange("baseUsage", 0, 0, Integer.MAX_VALUE); maxTransfer = builder.comment("The maximum energy that the Controller can receive") .defineInRange("maxTransfer", Integer.MAX_VALUE, 0, Integer.MAX_VALUE); builder.pop(); } public boolean getUseEnergy() { return useEnergy.get(); } public int getCapacity() { return capacity.get(); } public int getBaseUsage() { return baseUsage.get(); } public int getMaxTransfer() { return maxTransfer.get(); } } public class Cable { private final ModConfigSpec.IntValue usage; public Cable() { builder.push("cable"); usage = builder.comment("The energy used by the Cable").defineInRange("usage", 0, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class DiskDrive { private final ModConfigSpec.IntValue usage; private final ModConfigSpec.IntValue diskUsage; public DiskDrive() { builder.push("diskDrive"); usage = builder.comment("The energy used by the Disk Drive").defineInRange("usage", 0, 0, Integer.MAX_VALUE); diskUsage = builder.comment("The energy used per disk in the Disk Drive") .defineInRange("diskUsage", 1, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } public int getDiskUsage() { return diskUsage.get(); } } public class Grid { private final ModConfigSpec.IntValue gridUsage; private final ModConfigSpec.IntValue craftingGridUsage; private final ModConfigSpec.IntValue patternGridUsage; private final ModConfigSpec.IntValue fluidGridUsage; public Grid() { builder.push("grid"); gridUsage = builder.comment("The energy used by Grids").defineInRange("gridUsage", 2, 0, Integer.MAX_VALUE); craftingGridUsage = builder.comment("The energy used by Crafting Grids") .defineInRange("craftingGridUsage", 4, 0, Integer.MAX_VALUE); patternGridUsage = builder.comment("The energy used by Pattern Grids") .defineInRange("patternGridUsage", 4, 0, Integer.MAX_VALUE); fluidGridUsage = builder.comment("The energy used by Fluid Grids") .defineInRange("fluidGridUsage", 2, 0, Integer.MAX_VALUE); builder.pop(); } public int getGridUsage() { return gridUsage.get(); } public int getCraftingGridUsage() { return craftingGridUsage.get(); } public int getPatternGridUsage() { return patternGridUsage.get(); } public int getFluidGridUsage() { return fluidGridUsage.get(); } } public class Upgrades { private final ModConfigSpec.IntValue rangeUpgradeUsage; private final ModConfigSpec.IntValue speedUpgradeUsage; private final ModConfigSpec.IntValue craftingUpgradeUsage; private final ModConfigSpec.IntValue stackUpgradeUsage; private final ModConfigSpec.IntValue silkTouchUpgradeUsage; private final ModConfigSpec.IntValue fortune1UpgradeUsage; private final ModConfigSpec.IntValue fortune2UpgradeUsage; private final ModConfigSpec.IntValue fortune3UpgradeUsage; private final ModConfigSpec.IntValue regulatorUpgradeUsage; public Upgrades() { builder.push("upgrades"); rangeUpgradeUsage = builder.comment("The additional energy used by the Range Upgrade") .defineInRange("rangeUpgradeUsage", 8, 0, Integer.MAX_VALUE); speedUpgradeUsage = builder.comment("The additional energy used by the Speed Upgrade") .defineInRange("speedUpgradeUsage", 2, 0, Integer.MAX_VALUE); craftingUpgradeUsage = builder.comment("The additional energy used by the Crafting Upgrade") .defineInRange("craftingUpgradeUsage", 5, 0, Integer.MAX_VALUE); stackUpgradeUsage = builder.comment("The additional energy used by the Stack Upgrade") .defineInRange("stackUpgradeUsage", 12, 0, Integer.MAX_VALUE); silkTouchUpgradeUsage = builder.comment("The additional energy used by the Silk Touch Upgrade") .defineInRange("silkTouchUpgradeUsage", 15, 0, Integer.MAX_VALUE); fortune1UpgradeUsage = builder.comment("The additional energy used by the Fortune 1 Upgrade") .defineInRange("fortune1UpgradeUsage", 10, 0, Integer.MAX_VALUE); fortune2UpgradeUsage = builder.comment("The additional energy used by the Fortune 2 Upgrade") .defineInRange("fortune2UpgradeUsage", 12, 0, Integer.MAX_VALUE); fortune3UpgradeUsage = builder.comment("The additional energy used by the Fortune 3 Upgrade") .defineInRange("fortune3UpgradeUsage", 14, 0, Integer.MAX_VALUE); regulatorUpgradeUsage = builder.comment("The additional energy used by the Regulator Upgrade") .defineInRange("regulatorUpgradeUsage", 15, 0, Integer.MAX_VALUE); builder.pop(); } public int getRangeUpgradeUsage() { return rangeUpgradeUsage.get(); } public int getSpeedUpgradeUsage() { return speedUpgradeUsage.get(); } public int getCraftingUpgradeUsage() { return craftingUpgradeUsage.get(); } public int getStackUpgradeUsage() { return stackUpgradeUsage.get(); } public int getSilkTouchUpgradeUsage() { return silkTouchUpgradeUsage.get(); } public int getFortune1UpgradeUsage() { return fortune1UpgradeUsage.get(); } public int getFortune2UpgradeUsage() { return fortune2UpgradeUsage.get(); } public int getFortune3UpgradeUsage() { return fortune3UpgradeUsage.get(); } public int getRegulatorUpgradeUsage() { return regulatorUpgradeUsage.get(); } } public class StorageBlock { private final ModConfigSpec.IntValue oneKUsage; private final ModConfigSpec.IntValue fourKUsage; private final ModConfigSpec.IntValue sixteenKUsage; private final ModConfigSpec.IntValue sixtyFourKUsage; private final ModConfigSpec.IntValue creativeUsage; public StorageBlock() { builder.push("storageBlock"); oneKUsage = builder.comment("The energy used by the 1k Storage Block") .defineInRange("oneKUsage", 2, 0, Integer.MAX_VALUE); fourKUsage = builder.comment("The energy used by the 4k Storage Block") .defineInRange("fourKUsage", 4, 0, Integer.MAX_VALUE); sixteenKUsage = builder.comment("The energy used by the 16k Storage Block") .defineInRange("sixteenKUsage", 6, 0, Integer.MAX_VALUE); sixtyFourKUsage = builder.comment("The energy used by the 64k Storage Block") .defineInRange("sixtyFourKUsage", 8, 0, Integer.MAX_VALUE); creativeUsage = builder.comment("The energy used by the Creative Storage Block") .defineInRange("creativeUsage", 10, 0, Integer.MAX_VALUE); builder.pop(); } public int getOneKUsage() { return oneKUsage.get(); } public int getFourKUsage() { return fourKUsage.get(); } public int getSixteenKUsage() { return sixteenKUsage.get(); } public int getSixtyFourKUsage() { return sixtyFourKUsage.get(); } public int getCreativeUsage() { return creativeUsage.get(); } } public class FluidStorageBlock { private final ModConfigSpec.IntValue sixtyFourKUsage; private final ModConfigSpec.IntValue twoHundredFiftySixKUsage; private final ModConfigSpec.IntValue thousandTwentyFourKUsage; private final ModConfigSpec.IntValue fourThousandNinetySixKUsage; private final ModConfigSpec.IntValue creativeUsage; public FluidStorageBlock() { builder.push("fluidStorageBlock"); sixtyFourKUsage = builder.comment("The energy used by the 64k Fluid Storage Block") .defineInRange("sixtyFourKUsage", 2, 0, Integer.MAX_VALUE); twoHundredFiftySixKUsage = builder.comment("The energy used by the 256k Fluid Storage Block") .defineInRange("twoHundredFiftySixKUsage", 4, 0, Integer.MAX_VALUE); thousandTwentyFourKUsage = builder.comment("The energy used by the 1024k Fluid Storage Block") .defineInRange("thousandTwentyFourKUsage", 6, 0, Integer.MAX_VALUE); fourThousandNinetySixKUsage = builder.comment("The energy used by the 4096k Fluid Storage Block") .defineInRange("fourThousandNinetySixKUsage", 8, 0, Integer.MAX_VALUE); creativeUsage = builder.comment("The energy used by the Creative Fluid Storage Block") .defineInRange("creativeUsage", 10, 0, Integer.MAX_VALUE); builder.pop(); } public int getSixtyFourKUsage() { return sixtyFourKUsage.get(); } public int getTwoHundredFiftySixKUsage() { return twoHundredFiftySixKUsage.get(); } public int getThousandTwentyFourKUsage() { return thousandTwentyFourKUsage.get(); } public int getFourThousandNinetySixKUsage() { return fourThousandNinetySixKUsage.get(); } public int getCreativeUsage() { return creativeUsage.get(); } } public class ExternalStorage { private final ModConfigSpec.IntValue usage; public ExternalStorage() { builder.push("externalStorage"); usage = builder.comment("The energy used by the External Storage") .defineInRange("usage", 6, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Importer { private final ModConfigSpec.IntValue usage; public Importer() { builder.push("importer"); usage = builder.comment("The energy used by the Importer").defineInRange("usage", 1, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Exporter { private final ModConfigSpec.IntValue usage; public Exporter() { builder.push("exporter"); usage = builder.comment("The energy used by the Exporter").defineInRange("usage", 1, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class NetworkReceiver { private final ModConfigSpec.IntValue usage; public NetworkReceiver() { builder.push("networkReceiver"); usage = builder.comment("The energy used by the Network Receiver") .defineInRange("usage", 0, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class NetworkTransmitter { private final ModConfigSpec.IntValue usage; public NetworkTransmitter() { builder.push("networkTransmitter"); usage = builder.comment("The energy used by the Network Transmitter") .defineInRange("usage", 64, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Relay { private final ModConfigSpec.IntValue usage; public Relay() { builder.push("relay"); usage = builder.comment("The energy used by the Relay").defineInRange("usage", 1, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Detector { private final ModConfigSpec.IntValue usage; public Detector() { builder.push("detector"); usage = builder.comment("The energy used by the Detector").defineInRange("usage", 2, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class SecurityManager { private final ModConfigSpec.IntValue usage; private final ModConfigSpec.IntValue usagePerCard; public SecurityManager() { builder.push("securityManager"); usage = builder.comment("The energy used by the Security Manager") .defineInRange("usage", 4, 0, Integer.MAX_VALUE); usagePerCard = builder.comment("The additional energy used by Security Cards in the Security Manager") .defineInRange("usagePerCard", 10, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } public int getUsagePerCard() { return usagePerCard.get(); } } public class Interface { private final ModConfigSpec.IntValue usage; public Interface() { builder.push("interface"); usage = builder.comment("The energy used by the Interface").defineInRange("usage", 2, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class FluidInterface { private final ModConfigSpec.IntValue usage; public FluidInterface() { builder.push("fluidInterface"); usage = builder.comment("The energy used by the Fluid Interface") .defineInRange("usage", 2, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class WirelessTransmitter { private final ModConfigSpec.IntValue usage; private final ModConfigSpec.IntValue baseRange; private final ModConfigSpec.IntValue rangePerUpgrade; public WirelessTransmitter() { builder.push("wirelessTransmitter"); usage = builder.comment("The energy used by the Wireless Transmitter") .defineInRange("usage", 8, 0, Integer.MAX_VALUE); baseRange = builder.comment("The base range of the Wireless Transmitter") .defineInRange("baseRange", 16, 0, Integer.MAX_VALUE); rangePerUpgrade = builder.comment("The additional range per Range Upgrade in the Wireless Transmitter") .defineInRange("rangePerUpgrade", 8, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } public int getBaseRange() { return baseRange.get(); } public int getRangePerUpgrade() { return rangePerUpgrade.get(); } } public class StorageMonitor { private final ModConfigSpec.IntValue usage; public StorageMonitor() { builder.push("storageMonitor"); usage = builder.comment("The energy used by the Storage Monitor") .defineInRange("usage", 3, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class WirelessGrid { private final ModConfigSpec.BooleanValue useEnergy; private final ModConfigSpec.IntValue capacity; private final ModConfigSpec.IntValue openUsage; private final ModConfigSpec.IntValue extractUsage; private final ModConfigSpec.IntValue insertUsage; public WirelessGrid() { builder.push("wirelessGrid"); useEnergy = builder.comment("Whether the Wireless Grid uses energy").define("useEnergy", true); capacity = builder.comment("The energy capacity of the Wireless Grid") .defineInRange("capacity", 3200, 0, Integer.MAX_VALUE); openUsage = builder.comment("The energy used by the Wireless Grid to open") .defineInRange("openUsage", 30, 0, Integer.MAX_VALUE); extractUsage = builder.comment("The energy used by the Wireless Grid to extract items") .defineInRange("extractUsage", 5, 0, Integer.MAX_VALUE); insertUsage = builder.comment("The energy used by the Wireless Grid to insert items") .defineInRange("insertUsage", 5, 0, Integer.MAX_VALUE); builder.pop(); } public boolean getUseEnergy() { return useEnergy.get(); } public int getCapacity() { return capacity.get(); } public int getOpenUsage() { return openUsage.get(); } public int getExtractUsage() { return extractUsage.get(); } public int getInsertUsage() { return insertUsage.get(); } } public class WirelessFluidGrid { private final ModConfigSpec.BooleanValue useEnergy; private final ModConfigSpec.IntValue capacity; private final ModConfigSpec.IntValue openUsage; private final ModConfigSpec.IntValue extractUsage; private final ModConfigSpec.IntValue insertUsage; public WirelessFluidGrid() { builder.push("wirelessFluidGrid"); useEnergy = builder.comment("Whether the Wireless Fluid Grid uses energy").define("useEnergy", true); capacity = builder.comment("The energy capacity of the Wireless Fluid Grid") .defineInRange("capacity", 3200, 0, Integer.MAX_VALUE); openUsage = builder.comment("The energy used by the Wireless Fluid Grid to open") .defineInRange("openUsage", 30, 0, Integer.MAX_VALUE); extractUsage = builder.comment("The energy used by the Wireless Fluid Grid to extract fluids") .defineInRange("extractUsage", 5, 0, Integer.MAX_VALUE); insertUsage = builder.comment("The energy used by the Wireless Fluid Grid to insert fluids") .defineInRange("insertUsage", 5, 0, Integer.MAX_VALUE); builder.pop(); } public boolean getUseEnergy() { return useEnergy.get(); } public int getCapacity() { return capacity.get(); } public int getOpenUsage() { return openUsage.get(); } public int getExtractUsage() { return extractUsage.get(); } public int getInsertUsage() { return insertUsage.get(); } } public class PortableGrid { private final ModConfigSpec.BooleanValue useEnergy; private final ModConfigSpec.IntValue capacity; private final ModConfigSpec.IntValue openUsage; private final ModConfigSpec.IntValue extractUsage; private final ModConfigSpec.IntValue insertUsage; public PortableGrid() { builder.push("portableGrid"); useEnergy = builder.comment("Whether the Portable Grid uses energy").define("useEnergy", true); capacity = builder.comment("The energy capacity of the Portable Grid") .defineInRange("capacity", 3200, 0, Integer.MAX_VALUE); openUsage = builder.comment("The energy used by the Portable Grid to open") .defineInRange("openUsage", 30, 0, Integer.MAX_VALUE); extractUsage = builder.comment("The energy used by the Portable Grid to extract items or fluids") .defineInRange("extractUsage", 5, 0, Integer.MAX_VALUE); insertUsage = builder.comment("The energy used by the Portable Grid to insert items or fluids") .defineInRange("insertUsage", 5, 0, Integer.MAX_VALUE); builder.pop(); } public boolean getUseEnergy() { return useEnergy.get(); } public int getCapacity() { return capacity.get(); } public int getOpenUsage() { return openUsage.get(); } public int getExtractUsage() { return extractUsage.get(); } public int getInsertUsage() { return insertUsage.get(); } } public class Constructor { private final ModConfigSpec.IntValue usage; public Constructor() { builder.push("constructor"); usage = builder.comment("The energy used by the Constructor").defineInRange("usage", 3, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Destructor { private final ModConfigSpec.IntValue usage; public Destructor() { builder.push("destructor"); usage = builder.comment("The energy used by the Destructor").defineInRange("usage", 3, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class DiskManipulator { private final ModConfigSpec.IntValue usage; public DiskManipulator() { builder.push("diskManipulator"); usage = builder.comment("The energy used by the Disk Manipulator") .defineInRange("usage", 4, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class Crafter { private final ModConfigSpec.IntValue usage; private final ModConfigSpec.IntValue patternUsage; public Crafter() { builder.push("crafter"); usage = builder.comment("The energy used by the Crafter").defineInRange("usage", 4, 0, Integer.MAX_VALUE); patternUsage = builder.comment("The energy used for every Pattern in the Crafter") .defineInRange("patternUsage", 1, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } public int getPatternUsage() { return patternUsage.get(); } } public class CrafterManager { private final ModConfigSpec.IntValue usage; public CrafterManager() { builder.push("crafterManager"); usage = builder.comment("The energy used by the Crafter Manager") .defineInRange("usage", 8, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class CraftingMonitor { private final ModConfigSpec.IntValue usage; public CraftingMonitor() { builder.push("craftingMonitor"); usage = builder.comment("The energy used by the Crafting Monitor") .defineInRange("usage", 8, 0, Integer.MAX_VALUE); builder.pop(); } public int getUsage() { return usage.get(); } } public class WirelessCraftingMonitor { private final ModConfigSpec.BooleanValue useEnergy; private final ModConfigSpec.IntValue capacity; private final ModConfigSpec.IntValue openUsage; private final ModConfigSpec.IntValue cancelUsage; private final ModConfigSpec.IntValue cancelAllUsage; public WirelessCraftingMonitor() { builder.push("wirelessCraftingMonitor"); useEnergy = builder.comment("Whether the Wireless Crafting Monitor uses energy").define("useEnergy", true); capacity = builder.comment("The energy capacity of the Wireless Crafting Monitor") .defineInRange("capacity", 3200, 0, Integer.MAX_VALUE); openUsage = builder.comment("The energy used by the Wireless Crafting Monitor to open") .defineInRange("openUsage", 30, 0, Integer.MAX_VALUE); cancelUsage = builder.comment("The energy used by the Wireless Crafting Monitor to cancel a crafting task") .defineInRange("cancelUsage", 5, 0, Integer.MAX_VALUE); cancelAllUsage = builder.comment("The energy used by the Wireless Crafting Monitor to cancel all crafting tasks") .defineInRange("cancelAllUsage", 10, 0, Integer.MAX_VALUE); builder.pop(); } public boolean getUseEnergy() { return useEnergy.get(); } public int getCapacity() { return capacity.get(); } public int getOpenUsage() { return openUsage.get(); } public int getCancelUsage() { return cancelUsage.get(); } public int getCancelAllUsage() { return cancelAllUsage.get(); } } public class Autocrafting { private final ModConfigSpec.IntValue calculationTimeoutMs; public Autocrafting() { builder.push("autocrafting"); calculationTimeoutMs = builder.comment( "The autocrafting calculation timeout in milliseconds, crafting tasks taking longer than this to calculate are cancelled to avoid server strain") .defineInRange("calculationTimeoutMs", 5000, 5000, Integer.MAX_VALUE); builder.pop(); } public int getCalculationTimeoutMs() { return calculationTimeoutMs.get(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/AlternativesContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import net.minecraft.world.entity.player.Player; public class AlternativesContainerMenu extends BaseContainerMenu { public AlternativesContainerMenu(Player player) { super(null, null, player, 0); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/AmountContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.container.slot.DisabledSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.ItemStackHandler; public class AmountContainerMenu extends BaseContainerMenu { public AmountContainerMenu(Player player, ItemStack stack) { super(null, null, player, 0); ItemStackHandler inventory = new ItemStackHandler(1); inventory.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(stack, 1)); addSlot(new DisabledSlot(inventory, 0, 89, 48)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/BaseContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyDisabledSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot; import com.refinedmods.refinedstorage.container.transfer.TransferManager; import com.refinedmods.refinedstorage.network.FluidFilterSlotUpdateMessage; import com.refinedmods.refinedstorage.blockentity.BaseBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationWatcher; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public abstract class BaseContainerMenu extends AbstractContainerMenu { protected final TransferManager transferManager = new TransferManager(this); @Nullable private final BaseBlockEntity blockEntity; private final Player player; private final List fluidSlots = new ArrayList<>(); private final List fluids = new ArrayList<>(); @Nullable private BlockEntitySynchronizationWatcher listener; protected BaseContainerMenu(@Nullable MenuType type, @Nullable BaseBlockEntity blockEntity, Player player, int windowId) { super(type, windowId); this.blockEntity = blockEntity; if (blockEntity != null && player instanceof ServerPlayer) { listener = new BlockEntitySynchronizationWatcher((ServerPlayer) player, blockEntity.getDataManager()); } this.player = player; } public Player getPlayer() { return player; } @Nullable public BaseBlockEntity getBlockEntity() { return blockEntity; } protected void addPlayerInventory(int xInventory, int yInventory) { int disabledSlotNumber = getDisabledSlotNumber(); int id = 9; for (int y = 0; y < 3; y++) { for (int x = 0; x < 9; x++) { if (id == disabledSlotNumber) { addSlot(new LegacyDisabledSlot(player.getInventory(), id, xInventory + x * 18, yInventory + y * 18)); } else { addSlot(new Slot(player.getInventory(), id, xInventory + x * 18, yInventory + y * 18)); } id++; } } id = 0; for (int i = 0; i < 9; i++) { int x = xInventory + i * 18; int y = yInventory + 4 + (3 * 18); if (id == disabledSlotNumber) { addSlot(new LegacyDisabledSlot(player.getInventory(), id, x, y)); } else { addSlot(new Slot(player.getInventory(), id, x, y)); } id++; } } public List getFluidSlots() { return fluidSlots; } @Override public void clicked(int id, int dragType, ClickType clickType, Player player) { Slot slot = id >= 0 ? getSlot(id) : null; int disabledSlotNumber = getDisabledSlotNumber(); // Prevent swapping disabled held item with the number keys (dragType is the slot we're swapping with) if (disabledSlotNumber != -1 && clickType == ClickType.SWAP && dragType == disabledSlotNumber) { return; } if (slot instanceof FilterSlot) { if (((FilterSlot) slot).isSizeAllowed()) { if (clickType == ClickType.QUICK_MOVE) { slot.set(ItemStack.EMPTY); } else if (!player.containerMenu.getCarried().isEmpty()) { slot.set(player.containerMenu.getCarried().copy()); } } else if (player.containerMenu.getCarried().isEmpty()) { slot.set(ItemStack.EMPTY); } else if (slot.mayPlace(player.containerMenu.getCarried())) { slot.set(player.containerMenu.getCarried().copy()); } return; } else if (slot instanceof FluidFilterSlot) { if (((FluidFilterSlot) slot).isSizeAllowed()) { if (clickType == ClickType.QUICK_MOVE) { ((FluidFilterSlot) slot).onContainerClicked(ItemStack.EMPTY); } else if (!player.containerMenu.getCarried().isEmpty()) { ((FluidFilterSlot) slot).onContainerClicked(player.containerMenu.getCarried()); } } else if (player.containerMenu.getCarried().isEmpty()) { ((FluidFilterSlot) slot).onContainerClicked(ItemStack.EMPTY); } else { ((FluidFilterSlot) slot).onContainerClicked(player.containerMenu.getCarried()); } return; } else if (slot instanceof LegacyFilterSlot) { if (player.containerMenu.getCarried().isEmpty()) { slot.set(ItemStack.EMPTY); } else if (slot.mayPlace(player.containerMenu.getCarried())) { slot.set(player.containerMenu.getCarried().copy()); } return; } else if (slot instanceof LegacyDisabledSlot) { return; } super.clicked(id, dragType, clickType, player); } @Override public ItemStack quickMoveStack(Player player, int slotIndex) { return transferManager.transfer(slotIndex); } @Override public boolean stillValid(Player player) { return isBlockEntityStillPresent(); } private boolean isBlockEntityStillPresent() { if (blockEntity != null) { return blockEntity.getLevel().getBlockEntity(blockEntity.getBlockPos()) == blockEntity; } return true; } @Override public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { if (slot instanceof FilterSlot || slot instanceof FluidFilterSlot || slot instanceof LegacyFilterSlot) { return false; } return super.canTakeItemForPickAll(stack, slot); } protected int getDisabledSlotNumber() { return -1; } @Override protected Slot addSlot(Slot slot) { if (slot instanceof FluidFilterSlot) { fluids.add(FluidStack.EMPTY); fluidSlots.add((FluidFilterSlot) slot); } return super.addSlot(slot); } @Override public void broadcastChanges() { super.broadcastChanges(); // Prevent sending changes about a tile that doesn't exist anymore. // 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). if (listener != null && isBlockEntityStillPresent()) { listener.detectAndSendChanges(); } if (this.getPlayer() instanceof ServerPlayer) { for (int i = 0; i < this.fluidSlots.size(); ++i) { FluidFilterSlot slot = this.fluidSlots.get(i); FluidStack cached = this.fluids.get(i); FluidStack actual = slot.getFluidInventory().getFluid(slot.getSlotIndex()); if (!API.instance().getComparer().isEqual(cached, actual, IComparer.COMPARE_QUANTITY | IComparer.COMPARE_NBT)) { this.fluids.set(i, actual.copy()); RS.NETWORK_HANDLER.sendTo((ServerPlayer) getPlayer(), new FluidFilterSlotUpdateMessage(((Slot) slot).index, actual)); } } } } @Override public void removed(Player player) { super.removed(player); if (listener != null) { listener.onClosed(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/ConstructorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class ConstructorContainerMenu extends BaseContainerMenu { public ConstructorContainerMenu(ConstructorBlockEntity constructor, Player player, int windowId) { super(RSContainerMenus.CONSTRUCTOR.get(), constructor, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(constructor.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } addSlot(new FilterSlot(constructor.getNode().getItemFilters(), 0, 80, 20).setEnableHandler(() -> constructor.getNode().getType() == IType.ITEMS)); addSlot(new FluidFilterSlot(constructor.getNode().getFluidFilters(), 0, 80, 20, 0).setEnableHandler(() -> constructor.getNode().getType() == IType.FLUIDS)); addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), constructor.getNode().getUpgrades()); transferManager.addFilterTransfer(player.getInventory(), constructor.getNode().getItemFilters(), constructor.getNode().getFluidFilters(), constructor.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/ControllerContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity; import net.minecraft.world.entity.player.Player; public class ControllerContainerMenu extends BaseContainerMenu { public ControllerContainerMenu(ControllerBlockEntity controller, Player player, int windowId) { super(RSContainerMenus.CONTROLLER.get(), controller, player, windowId); addPlayerInventory(8, 99); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/CrafterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class CrafterContainerMenu extends BaseContainerMenu { public CrafterContainerMenu(CrafterBlockEntity crafter, Player player, int windowId) { super(RSContainerMenus.CRAFTER.get(), crafter, player, windowId); for (int i = 0; i < 9; ++i) { addSlot(new SlotItemHandler(crafter.getNode().getPatternInventory(), i, 8 + (18 * i), 20)); } for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(crafter.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), crafter.getNode().getUpgrades()); transferManager.addBiTransfer(player.getInventory(), crafter.getNode().getPatternInventory()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/CrafterManagerContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode; import com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.PatternItemValidator; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.screen.IScreenInfoProvider; import com.refinedmods.refinedstorage.screen.grid.filtering.GridFilterParser; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Predicate; public class CrafterManagerContainerMenu extends BaseContainerMenu { private final CrafterManagerNetworkNode crafterManager; private final Map dummyInventories = new HashMap<>(); private final Map headings = new HashMap<>(); private IScreenInfoProvider screenInfoProvider; private Map containerData; private int rows; public CrafterManagerContainerMenu(CrafterManagerBlockEntity crafterManager, Player player, int windowId) { super(RSContainerMenus.CRAFTER_MANAGER.get(), crafterManager, player, windowId); this.crafterManager = crafterManager.getNode(); } public void setScreenInfoProvider(IScreenInfoProvider infoProvider) { this.screenInfoProvider = infoProvider; } public void initSlotsServer() { addPlayerInventory(8, screenInfoProvider.getYPlayerInventory()); if (crafterManager.getNetwork() != null) { for (Map.Entry> entry : crafterManager.getNetwork().getCraftingManager().getNamedContainers().entrySet()) { for (IItemHandlerModifiable handler : entry.getValue()) { for (int i = 0; i < handler.getSlots(); ++i) { addSlot(new CrafterManagerSlot(handler, i, 0, 0, true, screenInfoProvider, crafterManager)); } } } } } public void initSlots(@Nullable Map data) { if (data != null) { this.containerData = data; } this.slots.clear(); this.lastSlots.clear(); this.headings.clear(); this.rows = 0; addPlayerInventory(8, screenInfoProvider.getYPlayerInventory()); int y = 19 + 18 - screenInfoProvider.getCurrentOffset() * 18; int x = 8; Predicate filters = GridFilterParser.getFilters(null, screenInfoProvider.getSearchFieldText(), Collections.emptyList()); for (Map.Entry category : containerData.entrySet()) { IItemHandlerModifiable dummy; if (data == null) { // We're only resizing, get the previous inventory... dummy = dummyInventories.get(category.getKey()); } else { dummy = new BaseItemHandler(category.getValue()) { @Override public int getSlotLimit(int slot) { return 1; } @Nonnull @Override public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { if (new PatternItemValidator(getPlayer().getCommandSenderWorld()).test(stack)) { return super.insertItem(slot, stack, simulate); } return stack; } }; dummyInventories.put(category.getKey(), dummy); } boolean foundItemsInCategory = false; int yHeading = y - 19; int slotFound = 0; for (int slot = 0; slot < category.getValue(); ++slot) { boolean visible = true; if (!screenInfoProvider.getSearchFieldText().trim().isEmpty()) { ItemStack stack = dummy.getStackInSlot(slot); if (stack.isEmpty()) { visible = false; } else { ICraftingPattern pattern = PatternItem.fromCache(crafterManager.getLevel(), stack); visible = false; if (pattern.isValid()) { for (ItemStack output : pattern.getOutputs()) { ItemGridStack outputConverted = new ItemGridStack(output); if (filters.test(outputConverted)) { visible = true; break; } } } } } addSlot(new CrafterManagerSlot(dummy, slot, x, y, visible, screenInfoProvider, crafterManager)); if (visible) { foundItemsInCategory = true; x += 18; // Don't increase y level if we are on our last slot row (otherwise we do y += 18 * 3) if ((slotFound + 1) % 9 == 0 && slot + 1 < category.getValue()) { x = 8; y += 18; rows++; } slotFound++; } } if (foundItemsInCategory) { headings.put(category.getKey(), yHeading); x = 8; y += 18 * 2; rows += 2; // Heading and first row } } } public Map getHeadings() { return headings; } public int getRows() { return rows; } @Override public ItemStack quickMoveStack(Player player, int index) { ItemStack stack = ItemStack.EMPTY; Slot slot = getSlot(index); if (slot.hasItem()) { stack = slot.getItem(); if (!new PatternItemValidator(getPlayer().getCommandSenderWorld()).test(stack)) { return ItemStack.EMPTY; } if (index < 9 * 4) { if (!moveItemStackTo(stack, 9 * 4, slots.size(), false)) { return ItemStack.EMPTY; } } else if (!moveItemStackTo(stack, 0, 9 * 4, false)) { return ItemStack.EMPTY; } if (stack.getCount() == 0) { slot.set(ItemStack.EMPTY); } else { slot.setChanged(); } } return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/CraftingMonitorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingManager; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorListener; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorSyncTask; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; public class CraftingMonitorContainerMenu extends BaseContainerMenu implements ICraftingMonitorListener { private final ICraftingMonitor craftingMonitor; private boolean addedListener; public CraftingMonitorContainerMenu(MenuType type, ICraftingMonitor craftingMonitor, @Nullable CraftingMonitorBlockEntity blockEntity, Player player, int windowId) { super(type, blockEntity, player, windowId); this.craftingMonitor = craftingMonitor; } @Override public void broadcastChanges() { super.broadcastChanges(); if (!getPlayer().level().isClientSide) { ICraftingManager manager = craftingMonitor.getCraftingManager(); if (manager != null && !addedListener) { manager.addListener(this); this.addedListener = true; } else if (manager == null && addedListener) { this.addedListener = false; } } } @Override public void removed(Player player) { super.removed(player); if (!player.getCommandSenderWorld().isClientSide) { craftingMonitor.onClosed(player); ICraftingManager manager = craftingMonitor.getCraftingManager(); if (manager != null && addedListener) { manager.removeListener(this); } } } public ICraftingMonitor getCraftingMonitor() { return craftingMonitor; } @Override public ItemStack quickMoveStack(Player player, int index) { ItemStack stack = ItemStack.EMPTY; Slot slot = getSlot(index); if (slot.hasItem()) { stack = slot.getItem(); if (index < 4) { if (!moveItemStackTo(stack, 4, slots.size(), false)) { return ItemStack.EMPTY; } } else if (!moveItemStackTo(stack, 0, 4, false)) { return ItemStack.EMPTY; } if (stack.getCount() == 0) { slot.set(ItemStack.EMPTY); } else { slot.setChanged(); } } return stack; } @Override protected int getDisabledSlotNumber() { return craftingMonitor.getSlotId(); } @Override public void onAttached() { onChanged(); } @Override public void onChanged() { RS.NETWORK_HANDLER.sendTo((ServerPlayer) getPlayer(), new CraftingMonitorUpdateMessage( craftingMonitor.getTasks().stream().map(task -> new CraftingMonitorSyncTask( task.getId(), task.getRequested(), task.getQuantity(), task.getStartTime(), task.getCompletionPercentage(), task.getCraftingMonitorElements() )).toList() )); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/CraftingSettingsContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.container.slot.DisabledSlot; import com.refinedmods.refinedstorage.container.slot.filter.DisabledFluidFilterSlot; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.ItemStackHandler; public class CraftingSettingsContainerMenu extends BaseContainerMenu { public CraftingSettingsContainerMenu(Player player, IGridStack stack) { super(null, null, player, 0); if (stack instanceof FluidGridStack) { FluidInventory inventory = new FluidInventory(1); inventory.setFluid(0, ((FluidGridStack) stack).getStack()); addSlot(new DisabledFluidFilterSlot(inventory, 0, 89, 48)); } else if (stack instanceof ItemGridStack) { ItemStackHandler handler = new ItemStackHandler(1); handler.setStackInSlot(0, ItemHandlerHelper.copyStackWithSize(((ItemGridStack) stack).getStack(), 1)); addSlot(new DisabledSlot(handler, 0, 89, 48)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/DestructorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class DestructorContainerMenu extends BaseContainerMenu { public DestructorContainerMenu(DestructorBlockEntity destructor, Player player, int windowId) { super(RSContainerMenus.DESTRUCTOR.get(), destructor, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(destructor.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(destructor.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> destructor.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(destructor.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> destructor.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), destructor.getNode().getUpgrades()); transferManager.addFilterTransfer(player.getInventory(), destructor.getNode().getItemFilters(), destructor.getNode().getFluidFilters(), destructor.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/DetectorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; public class DetectorContainerMenu extends BaseContainerMenu { public DetectorContainerMenu(DetectorBlockEntity detector, Player player, int windowId) { super(RSContainerMenus.DETECTOR.get(), detector, player, windowId); addSlot(new FilterSlot(detector.getNode().getItemFilters(), 0, 107, 20).setEnableHandler(() -> detector.getNode().getType() == IType.ITEMS)); addSlot(new FluidFilterSlot(detector.getNode().getFluidFilters(), 0, 107, 20).setEnableHandler(() -> detector.getNode().getType() == IType.FLUIDS)); addPlayerInventory(8, 55); transferManager.addFilterTransfer(player.getInventory(), detector.getNode().getItemFilters(), detector.getNode().getFluidFilters(), detector.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/DiskDriveContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class DiskDriveContainerMenu extends BaseContainerMenu { public DiskDriveContainerMenu(DiskDriveBlockEntity diskDrive, Player player, int windowId) { super(RSContainerMenus.DISK_DRIVE.get(), diskDrive, player, windowId); int x = 80; int y = 54; for (int i = 0; i < 8; ++i) { addSlot(new SlotItemHandler(diskDrive.getNode().getDisks(), i, x + ((i % 2) * 18), y + Math.floorDiv(i, 2) * 18)); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(diskDrive.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskDrive.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(diskDrive.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskDrive.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 141); transferManager.addBiTransfer(player.getInventory(), diskDrive.getNode().getDisks()); transferManager.addFilterTransfer(player.getInventory(), diskDrive.getNode().getItemFilters(), diskDrive.getNode().getFluidFilters(), diskDrive.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/DiskManipulatorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class DiskManipulatorContainerMenu extends BaseContainerMenu { public DiskManipulatorContainerMenu(DiskManipulatorBlockEntity diskManipulator, Player player, int windowId) { super(RSContainerMenus.DISK_MANIPULATOR.get(), diskManipulator, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(diskManipulator.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } for (int i = 0; i < 3; ++i) { addSlot(new SlotItemHandler(diskManipulator.getNode().getInputDisks(), i, 44, 57 + (i * 18))); } for (int i = 0; i < 3; ++i) { addSlot(new SlotItemHandler(diskManipulator.getNode().getOutputDisks(), i, 116, 57 + (i * 18))); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(diskManipulator.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskManipulator.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(diskManipulator.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> diskManipulator.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 129); transferManager.addBiTransfer(player.getInventory(), diskManipulator.getNode().getUpgrades()); transferManager.addBiTransfer(player.getInventory(), diskManipulator.getNode().getInputDisks()); transferManager.addTransfer(diskManipulator.getNode().getOutputDisks(), player.getInventory()); transferManager.addFilterTransfer(player.getInventory(), diskManipulator.getNode().getItemFilters(), diskManipulator.getNode().getFluidFilters(), diskManipulator.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/ExporterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class ExporterContainerMenu extends BaseContainerMenu { private final ExporterBlockEntity exporter; private boolean hasRegulatorMode; public ExporterContainerMenu(ExporterBlockEntity exporter, Player player, int windowId) { super(RSContainerMenus.EXPORTER.get(), exporter, player, windowId); this.exporter = exporter; this.hasRegulatorMode = hasRegulatorMode(); initSlots(); } private boolean hasRegulatorMode() { return exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR); } @Override public void broadcastChanges() { super.broadcastChanges(); boolean updatedHasRegulatorMode = hasRegulatorMode(); if (hasRegulatorMode != updatedHasRegulatorMode) { hasRegulatorMode = updatedHasRegulatorMode; initSlots(); } } public void initSlots() { this.slots.clear(); this.lastSlots.clear(); this.transferManager.clearTransfers(); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(exporter.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot( exporter.getNode().getItemFilters(), i, 8 + (18 * i), 20, exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR) ? FilterSlot.FILTER_ALLOW_SIZE : 0 ).setEnableHandler(() -> exporter.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot( exporter.getNode().getFluidFilters(), i, 8 + (18 * i), 20, exporter.getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR) ? FluidFilterSlot.FILTER_ALLOW_SIZE : 0 ).setEnableHandler(() -> exporter.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 55); transferManager.addBiTransfer(getPlayer().getInventory(), exporter.getNode().getUpgrades()); transferManager.addFilterTransfer(getPlayer().getInventory(), exporter.getNode().getItemFilters(), exporter.getNode().getFluidFilters(), exporter.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/ExternalStorageContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; public class ExternalStorageContainerMenu extends BaseContainerMenu { public ExternalStorageContainerMenu(ExternalStorageBlockEntity externalStorage, Player player, int windowId) { super(RSContainerMenus.EXTERNAL_STORAGE.get(), externalStorage, player, windowId); for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(externalStorage.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> externalStorage.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(externalStorage.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> externalStorage.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 141); transferManager.addFilterTransfer(player.getInventory(), externalStorage.getNode().getItemFilters(), externalStorage.getNode().getFluidFilters(), externalStorage.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/FilterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler; import com.refinedmods.refinedstorage.inventory.fluid.ConfiguredIconInFluidFilterItemHandler; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.ConfiguredIconInFilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.ConfiguredItemsInFilterItemHandler; import com.refinedmods.refinedstorage.item.FilterItem; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; public class FilterContainerMenu extends BaseContainerMenu { private final ItemStack filterItem; public FilterContainerMenu(Player player, ItemStack filterItem, int windowId) { super(RSContainerMenus.FILTER.get(), null, player, windowId); this.filterItem = filterItem; int y = 20; int x = 8; ConfiguredItemsInFilterItemHandler filter = new ConfiguredItemsInFilterItemHandler(filterItem); FluidInventory fluidFilter = new ConfiguredFluidsInFilterItemHandler(filterItem); for (int i = 0; i < 27; ++i) { addSlot(new FilterSlot(filter, i, x, y).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.ITEMS)); addSlot(new FluidFilterSlot(fluidFilter, i, x, y).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.FLUIDS)); if ((i + 1) % 9 == 0) { x = 8; y += 18; } else { x += 18; } } addSlot(new FilterSlot(new ConfiguredIconInFilterItemHandler(filterItem), 0, 8, 117).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.ITEMS)); addSlot(new FluidFilterSlot(new ConfiguredIconInFluidFilterItemHandler(filterItem), 0, 8, 117).setEnableHandler(() -> FilterItem.getType(filterItem) == IType.FLUIDS)); addPlayerInventory(8, 149); transferManager.addFilterTransfer(player.getInventory(), filter, fluidFilter, () -> FilterItem.getType(filterItem)); } public ItemStack getFilterItem() { return filterItem; } @Override protected int getDisabledSlotNumber() { return getPlayer().getInventory().selected; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/FluidAmountContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.container.slot.filter.DisabledFluidFilterSlot; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.fluids.FluidStack; public class FluidAmountContainerMenu extends BaseContainerMenu { public FluidAmountContainerMenu(Player player, FluidStack stack) { super(null, null, player, 0); FluidInventory inventory = new FluidInventory(1); inventory.setFluid(0, stack); addSlot(new DisabledFluidFilterSlot(inventory, 0, 89, 48, 0)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/FluidInterfaceContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class FluidInterfaceContainerMenu extends BaseContainerMenu { public FluidInterfaceContainerMenu(FluidInterfaceBlockEntity fluidInterface, Player player, int windowId) { super(RSContainerMenus.FLUID_INTERFACE.get(), fluidInterface, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(fluidInterface.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } addSlot(new SlotItemHandler(fluidInterface.getNode().getIn(), 0, 44, 32)); addSlot(new FluidFilterSlot(fluidInterface.getNode().getOut(), 0, 116, 32, FilterSlot.FILTER_ALLOW_SIZE)); addPlayerInventory(8, 122); transferManager.addBiTransfer(player.getInventory(), fluidInterface.getNode().getIn()); transferManager.addFluidFilterTransfer(player.getInventory(), fluidInterface.getNode().getOut()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/FluidStorageContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity; import net.minecraft.world.entity.player.Player; public class FluidStorageContainerMenu extends BaseContainerMenu { public FluidStorageContainerMenu(FluidStorageBlockEntity fluidStorage, Player player, int windowId) { super(RSContainerMenus.FLUID_STORAGE_BLOCK.get(), fluidStorage, player, windowId); for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(fluidStorage.getNode().getFilters(), i, 8 + (18 * i), 20)); } addPlayerInventory(8, 141); transferManager.addFluidFilterTransfer(player.getInventory(), fluidStorage.getNode().getFilters()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/GridContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.ICraftingGridListener; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.handler.IFluidGridHandler; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCacheListener; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.blockentity.BaseBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.container.slot.grid.CraftingGridSlot; import com.refinedmods.refinedstorage.container.slot.grid.ResultCraftingGridSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyBaseSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyDisabledSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot; import com.refinedmods.refinedstorage.screen.IScreenInfoProvider; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.ContainerListener; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.SlotItemHandler; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class GridContainerMenu extends BaseContainerMenu implements ICraftingGridListener { private final IGrid grid; private IStorageCache storageCache; private IStorageCacheListener storageCacheListener; private IScreenInfoProvider screenInfoProvider; private ResultCraftingGridSlot craftingResultSlot; private LegacyBaseSlot patternResultSlot; private List itemPatternSlots = new ArrayList<>(); private List fluidPatternSlots = new ArrayList<>(); private int patternScrollOffset; public GridContainerMenu(IGrid grid, @Nullable BaseBlockEntity blockEntity, Player player, int windowId) { super(RSContainerMenus.GRID.get(), blockEntity, player, windowId); this.grid = grid; grid.addCraftingListener(this); } public IScreenInfoProvider getScreenInfoProvider() { return screenInfoProvider; } public void setScreenInfoProvider(IScreenInfoProvider screenInfoProvider) { this.screenInfoProvider = screenInfoProvider; } public void initSlots() { this.slots.clear(); this.lastSlots.clear(); this.transferManager.clearTransfers(); addFilterSlots(); if (grid instanceof IPortableGrid) { addPortableGridSlots(); } if (grid.getGridType() == GridType.CRAFTING) { addCraftingSlots(); } else if (grid.getGridType() == GridType.PATTERN) { addPatternSlots(); } transferManager.setNotFoundHandler(slotIndex -> { if (!getPlayer().getCommandSenderWorld().isClientSide) { Slot slot = slots.get(slotIndex); if (grid instanceof IPortableGrid && slot instanceof SlotItemHandler && ((SlotItemHandler) slot).getItemHandler().equals(((IPortableGrid) grid).getDiskInventory())) { return ItemStack.EMPTY; } if (slot.hasItem()) { if (slot == craftingResultSlot) { grid.onCraftedShift(getPlayer()); broadcastChanges(); } else { ItemStack stack = slot.getItem(); if (grid.getGridType() == GridType.FLUID) { IFluidGridHandler fluidHandler = grid.getFluidHandler(); if (fluidHandler != null) { slot.set(fluidHandler.onInsert((ServerPlayer) getPlayer(), stack)); } } else { IItemGridHandler itemHandler = grid.getItemHandler(); if (itemHandler != null) { slot.set(itemHandler.onInsert((ServerPlayer) getPlayer(), stack, false)); } else if (slot instanceof CraftingGridSlot && moveItemStackTo(stack, 14, 14 + (9 * 4), false)) { slot.setChanged(); // This is needed because when a grid is disconnected, // and a player shift clicks from the matrix to the inventory (this if case), // the crafting inventory isn't being notified. grid.onCraftingMatrixChanged(); } } broadcastChanges(); } } } return ItemStack.EMPTY; }); addPlayerInventory(8, screenInfoProvider.getYPlayerInventory()); } private void addPortableGridSlots() { addSlot(new SlotItemHandler(((IPortableGrid) grid).getDiskInventory(), 0, 204, 6)); transferManager.addBiTransfer(getPlayer().getInventory(), ((IPortableGrid) grid).getDiskInventory()); } private void addFilterSlots() { int yStart = 6; if (grid instanceof IPortableGrid) { yStart = 38; } for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(grid.getFilter(), i, 204, yStart + (18 * i))); } transferManager.addBiTransfer(getPlayer().getInventory(), grid.getFilter()); } private void addCraftingSlots() { int headerAndSlots = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18); int x = 26; int y = headerAndSlots + 4; for (int i = 0; i < 9; ++i) { addSlot(new CraftingGridSlot(grid.getCraftingMatrix(), i, x, y)); x += 18; if ((i + 1) % 3 == 0) { y += 18; x = 26; } } craftingResultSlot = new ResultCraftingGridSlot(getPlayer(), grid, 0, 130 + 4, headerAndSlots + 22); addSlot(craftingResultSlot); } private void addPatternSlots() { itemPatternSlots.clear(); fluidPatternSlots.clear(); int headerAndSlots = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18); addSlot(new SlotItemHandler(((GridNetworkNode) grid).getPatterns(), 0, 172, headerAndSlots + 4)); addSlot(new SlotItemHandler(((GridNetworkNode) grid).getPatterns(), 1, 172, headerAndSlots + 40)); transferManager.addBiTransfer(getPlayer().getInventory(), ((GridNetworkNode) grid).getPatterns()); // Processing patterns int ox = 8; int x = ox; int y = headerAndSlots + 4; for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE * 2; ++i) { int itemFilterSlotConfig = FilterSlot.FILTER_ALLOW_SIZE; if (i < GridNetworkNode.PROCESSING_MATRIX_SIZE) { itemFilterSlotConfig |= FilterSlot.FILTER_ALLOW_ALTERNATIVES; } int fluidFilterSlotConfig = FluidFilterSlot.FILTER_ALLOW_SIZE; if (i < GridNetworkNode.PROCESSING_MATRIX_SIZE) { fluidFilterSlotConfig |= FluidFilterSlot.FILTER_ALLOW_ALTERNATIVES; } int finalI = i; itemPatternSlots.add(addSlot(new FilterSlot(((GridNetworkNode) grid).getProcessingMatrix(), i, x, y, itemFilterSlotConfig) .setEnableHandler(() -> getSlotEnabled(finalI, true)))); fluidPatternSlots.add(addSlot(new FluidFilterSlot(((GridNetworkNode) grid).getProcessingMatrixFluids(), i, x, y, fluidFilterSlotConfig) .setEnableHandler(() -> getSlotEnabled(finalI, false)))); x += 18; if ((i + 1) % 3 == 0) { if (i == GridNetworkNode.PROCESSING_MATRIX_SIZE - 1) { ox = 93; x = ox; y = headerAndSlots + 4; } else { x = ox; y += 18; } } } // Regular patterns x = 26; y = headerAndSlots + 4; for (int i = 0; i < 9; ++i) { addSlot(new LegacyFilterSlot(grid.getCraftingMatrix(), i, x, y).setEnableHandler(() -> !((GridNetworkNode) grid).isProcessingPattern())); x += 18; if ((i + 1) % 3 == 0) { y += 18; x = 26; } } patternResultSlot = new LegacyDisabledSlot(grid.getCraftingResult(), 0, 134, headerAndSlots + 22).setEnableHandler(() -> !((GridNetworkNode) grid).isProcessingPattern()); addSlot(patternResultSlot); } private boolean getSlotEnabled(int i, boolean item) { if (!((GridNetworkNode) grid).isProcessingPattern() || !isVisible(i)) { return false; } if (item) { if (itemPatternSlots.get(i).hasItem()) { return true; } if (((FluidFilterSlot) fluidPatternSlots.get(i)).hasStack()) { return false; } return ((GridNetworkNode) grid).getType() == IType.ITEMS; } else { if (((FluidFilterSlot) fluidPatternSlots.get(i)).hasStack()) { return true; } if (itemPatternSlots.get(i).hasItem()) { return false; } return ((GridNetworkNode) grid).getType() == IType.FLUIDS; } } private boolean isVisible(int slotNumber) { return (slotNumber >= patternScrollOffset * 3 && slotNumber < patternScrollOffset * 3 + 9) || (slotNumber >= patternScrollOffset * 3 + GridNetworkNode.PROCESSING_MATRIX_SIZE && slotNumber < patternScrollOffset * 3 + GridNetworkNode.PROCESSING_MATRIX_SIZE + 9); } public IGrid getGrid() { return grid; } @Override public void onCraftingMatrixChanged() { for (int i = 0; i < slots.size(); ++i) { Slot slot = slots.get(i); if (slot instanceof CraftingGridSlot || slot == craftingResultSlot || slot == patternResultSlot) { for (ContainerListener listener : containerListeners) { // @Volatile: We can't use ContainerListener#slotChanged since ServerPlayer blocks ResultSlot changes... if (listener instanceof ServerPlayer) { ((ServerPlayer) listener).connection.send(new ClientboundContainerSetSlotPacket(containerId, incrementStateId(), i, slot.getItem())); } } } } } @Override public void broadcastChanges() { if (!getPlayer().level().isClientSide) { // The grid is offline. if (grid.getStorageCache() == null) { // The grid just went offline, there is still a listener. if (storageCacheListener != null) { // Remove it from the previous cache and clean up. storageCache.removeListener(storageCacheListener); storageCacheListener = null; storageCache = null; } } else if (storageCacheListener == null) { // The grid came online. storageCacheListener = grid.createListener((ServerPlayer) getPlayer()); storageCache = grid.getStorageCache(); storageCache.addListener(storageCacheListener); } } super.broadcastChanges(); } @Override public void removed(Player player) { super.removed(player); if (!player.getCommandSenderWorld().isClientSide) { grid.onClosed(player); if (storageCache != null && storageCacheListener != null) { storageCache.removeListener(storageCacheListener); } } grid.removeCraftingListener(this); } @Override public boolean canTakeItemForPickAll(ItemStack stack, Slot slot) { if (slot == craftingResultSlot || slot == patternResultSlot) { return false; } return super.canTakeItemForPickAll(stack, slot); } @Override public int getDisabledSlotNumber() { return grid.getSlotId(); } public void updatePatternSlotPositions(int newOffset) { patternScrollOffset = newOffset; int yPosition = screenInfoProvider.getTopHeight() + (screenInfoProvider.getVisibleRows() * 18) + 4; int originalYPosition = yPosition; for (int i = 0; i < itemPatternSlots.size(); i++) { if (i == GridNetworkNode.PROCESSING_MATRIX_SIZE) { // reset when reaching output slots yPosition = originalYPosition; } if (isVisible(i)) { itemPatternSlots.get(i).y = yPosition; fluidPatternSlots.get(i).y = yPosition; if ((i + 1) % 3 == 0) { yPosition += 18; } } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/ImporterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class ImporterContainerMenu extends BaseContainerMenu { public ImporterContainerMenu(ImporterBlockEntity importer, Player player, int windowId) { super(RSContainerMenus.IMPORTER.get(), importer, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(importer.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(importer.getNode().getItemFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> importer.getNode().getType() == IType.ITEMS)); } for (int i = 0; i < 9; ++i) { addSlot(new FluidFilterSlot(importer.getNode().getFluidFilters(), i, 8 + (18 * i), 20).setEnableHandler(() -> importer.getNode().getType() == IType.FLUIDS)); } addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), importer.getNode().getUpgrades()); transferManager.addFilterTransfer(player.getInventory(), importer.getNode().getItemFilters(), importer.getNode().getFluidFilters(), importer.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/InterfaceContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.OutputSlot; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class InterfaceContainerMenu extends BaseContainerMenu { public InterfaceContainerMenu(InterfaceBlockEntity blockEntity, Player player, int windowId) { super(RSContainerMenus.INTERFACE.get(), blockEntity, player, windowId); for (int i = 0; i < 9; ++i) { addSlot(new SlotItemHandler(blockEntity.getNode().getImportItems(), i, 8 + (18 * i), 20)); } for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(blockEntity.getNode().getExportFilterItems(), i, 8 + (18 * i), 54, FilterSlot.FILTER_ALLOW_SIZE)); } for (int i = 0; i < 9; ++i) { addSlot(new OutputSlot(blockEntity.getNode().getExportItems(), i, 8 + (18 * i), 100)); } for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(blockEntity.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } addPlayerInventory(8, 134); transferManager.addBiTransfer(player.getInventory(), blockEntity.getNode().getUpgrades()); transferManager.addBiTransfer(player.getInventory(), blockEntity.getNode().getImportItems()); transferManager.addTransfer(blockEntity.getNode().getExportItems(), player.getInventory()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/NetworkTransmitterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class NetworkTransmitterContainerMenu extends BaseContainerMenu { public NetworkTransmitterContainerMenu(NetworkTransmitterBlockEntity networkTransmitter, Player player, int windowId) { super(RSContainerMenus.NETWORK_TRANSMITTER.get(), networkTransmitter, player, windowId); addSlot(new SlotItemHandler(networkTransmitter.getNode().getNetworkCard(), 0, 8, 20)); addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), networkTransmitter.getNode().getNetworkCard()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/RelayContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.blockentity.RelayBlockEntity; import net.minecraft.world.entity.player.Player; public class RelayContainerMenu extends BaseContainerMenu { public RelayContainerMenu(RelayBlockEntity relay, Player player, int windowId) { super(RSContainerMenus.RELAY.get(), relay, player, windowId); addPlayerInventory(8, 50); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/SecurityManagerContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class SecurityManagerContainerMenu extends BaseContainerMenu { private final SecurityManagerBlockEntity securityManager; public SecurityManagerContainerMenu(SecurityManagerBlockEntity securityManager, Player player, int windowId) { super(RSContainerMenus.SECURITY_MANAGER.get(), securityManager, player, windowId); int x = 8; int y = 20; for (int i = 0; i < 9 * 2; ++i) { addSlot(new SlotItemHandler(securityManager.getNode().getCardsItems(), i, x, y)); if (((i + 1) % 9) == 0) { x = 8; y += 18; } else { x += 18; } } addSlot(new SlotItemHandler(securityManager.getNode().getEditCard(), 0, 80, 70)); addPlayerInventory(8, 152); transferManager.addBiTransfer(player.getInventory(), securityManager.getNode().getCardsItems()); transferManager.addTransfer(securityManager.getNode().getEditCard(), player.getInventory()); this.securityManager = securityManager; } public void updatePermission(Permission permission, boolean state) { securityManager.getNode().updatePermission(permission, state); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/StorageContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.blockentity.StorageBlockEntity; import net.minecraft.world.entity.player.Player; public class StorageContainerMenu extends BaseContainerMenu { public StorageContainerMenu(StorageBlockEntity storage, Player player, int windowId) { super(RSContainerMenus.STORAGE_BLOCK.get(), storage, player, windowId); for (int i = 0; i < 9; ++i) { addSlot(new FilterSlot(storage.getNode().getFilters(), i, 8 + (18 * i), 20)); } addPlayerInventory(8, 141); transferManager.addItemFilterTransfer(player.getInventory(), storage.getNode().getFilters()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/StorageMonitorContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.entity.player.Player; public class StorageMonitorContainerMenu extends BaseContainerMenu { public StorageMonitorContainerMenu(StorageMonitorBlockEntity storageMonitor, Player player, int windowId) { super(RSContainerMenus.STORAGE_MONITOR.get(), storageMonitor, player, windowId); addSlot(new FilterSlot(storageMonitor.getNode().getItemFilters(), 0, 80, 20).setEnableHandler(() -> storageMonitor.getNode().getType() == IType.ITEMS)); addSlot(new FluidFilterSlot(storageMonitor.getNode().getFluidFilters(), 0, 80, 20).setEnableHandler(() -> storageMonitor.getNode().getType() == IType.FLUIDS)); addPlayerInventory(8, 55); transferManager.addFilterTransfer(player.getInventory(), storageMonitor.getNode().getItemFilters(), storageMonitor.getNode().getFluidFilters(), storageMonitor.getNode()::getType); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/WirelessTransmitterContainerMenu.java ================================================ package com.refinedmods.refinedstorage.container; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.items.SlotItemHandler; public class WirelessTransmitterContainerMenu extends BaseContainerMenu { public WirelessTransmitterContainerMenu(WirelessTransmitterBlockEntity wirelessTransmitter, Player player, int windowId) { super(RSContainerMenus.WIRELESS_TRANSMITTER.get(), wirelessTransmitter, player, windowId); for (int i = 0; i < 4; ++i) { addSlot(new SlotItemHandler(wirelessTransmitter.getNode().getUpgrades(), i, 187, 6 + (i * 18))); } addPlayerInventory(8, 55); transferManager.addBiTransfer(player.getInventory(), wirelessTransmitter.getNode().getUpgrades()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/BlockEntityContainerFactory.java ================================================ package com.refinedmods.refinedstorage.container.factory; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.IContainerFactory; public class BlockEntityContainerFactory implements IContainerFactory { private final Factory factory; public BlockEntityContainerFactory(Factory factory) { this.factory = factory; } @Override public C create(int windowId, Inventory inv, FriendlyByteBuf data) { BlockPos pos = data.readBlockPos(); T blockEntity = (T) inv.player.level().getBlockEntity(pos); return factory.create(windowId, inv, blockEntity); } public interface Factory { C create(int windowId, Inventory inv, T blockEntity); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/BlockEntityMenuProvider.java ================================================ package com.refinedmods.refinedstorage.container.factory; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class BlockEntityMenuProvider implements MenuProvider { private final Component name; private final Provider provider; private final BlockPos pos; public BlockEntityMenuProvider(Component name, Provider provider, BlockPos pos) { this.name = name; this.provider = provider; this.pos = pos; } @Override public Component getDisplayName() { return name; } @Nullable @Override public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) { T blockEntity = (T) player.level().getBlockEntity(pos); return provider.create(blockEntity, windowId, inventory, player); } public interface Provider { AbstractContainerMenu create(T blockEntity, int windowId, Inventory inventory, Player player); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/CrafterManagerContainerFactory.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu; import com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.neoforged.neoforge.network.IContainerFactory; import java.util.LinkedHashMap; import java.util.Map; public class CrafterManagerContainerFactory implements IContainerFactory { @Override public CrafterManagerContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf buf) { Map data = new LinkedHashMap<>(); BlockPos pos = buf.readBlockPos(); int size = buf.readInt(); for (int i = 0; i < size; ++i) { data.put(buf.readComponent().getString(), buf.readInt()); } CrafterManagerContainerMenu container = new CrafterManagerContainerMenu((CrafterManagerBlockEntity) inv.player.level().getBlockEntity(pos), inv.player, windowId); container.setScreenInfoProvider(new EmptyScreenInfoProvider()); container.initSlots(data); return container; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/CrafterManagerMenuProvider.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu; import com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.level.Level; import net.neoforged.neoforge.items.IItemHandlerModifiable; import javax.annotation.Nullable; import java.util.List; import java.util.Map; public class CrafterManagerMenuProvider implements MenuProvider { private final CrafterManagerBlockEntity blockEntity; public CrafterManagerMenuProvider(CrafterManagerBlockEntity blockEntity) { this.blockEntity = blockEntity; } public static void writeToBuffer(FriendlyByteBuf buf, Level level, BlockPos pos) { buf.writeBlockPos(pos); Map> containerData = ((CrafterManagerBlockEntity) level.getBlockEntity(pos)).getNode().getNetwork().getCraftingManager().getNamedContainers(); buf.writeInt(containerData.size()); for (Map.Entry> entry : containerData.entrySet()) { buf.writeComponent(entry.getKey()); int slots = 0; for (IItemHandlerModifiable handler : entry.getValue()) { slots += handler.getSlots(); } buf.writeInt(slots); } } @Override public Component getDisplayName() { return Component.translatable("gui.refinedstorage.crafter_manager"); } @Nullable @Override public AbstractContainerMenu createMenu(int windowId, Inventory playerInventory, Player playerEntity) { CrafterManagerContainerMenu container = new CrafterManagerContainerMenu(blockEntity, playerEntity, windowId); container.setScreenInfoProvider(new EmptyScreenInfoProvider()); container.initSlotsServer(); return container; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/CraftingMonitorContainerFactory.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.neoforged.neoforge.network.IContainerFactory; public class CraftingMonitorContainerFactory implements IContainerFactory { @Override public CraftingMonitorContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) { BlockPos pos = data.readBlockPos(); CraftingMonitorBlockEntity blockEntity = (CraftingMonitorBlockEntity) inv.player.level().getBlockEntity(pos); return new CraftingMonitorContainerMenu(RSContainerMenus.CRAFTING_MONITOR.get(), blockEntity.getNode(), blockEntity, inv.player, windowId); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/CraftingMonitorMenuProvider.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.CraftingMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor; import net.minecraft.network.chat.Component; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.MenuType; import javax.annotation.Nullable; public class CraftingMonitorMenuProvider implements MenuProvider { private final ICraftingMonitor craftingMonitor; @Nullable private final CraftingMonitorBlockEntity blockEntity; private final MenuType containerType; public CraftingMonitorMenuProvider(MenuType containerType, ICraftingMonitor craftingMonitor, @Nullable CraftingMonitorBlockEntity blockEntity) { this.containerType = containerType; this.craftingMonitor = craftingMonitor; this.blockEntity = blockEntity; } @Override public Component getDisplayName() { return craftingMonitor.getTitle(); } @Nullable @Override public AbstractContainerMenu createMenu(int windowId, Inventory playerInventory, Player playerEntity) { return new CraftingMonitorContainerMenu(containerType, craftingMonitor, blockEntity, playerEntity, windowId); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/GridContainerFactory.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.blockentity.BaseBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.IContainerFactory; import org.apache.commons.lang3.tuple.Pair; public class GridContainerFactory implements IContainerFactory { @Override public GridContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) { ResourceLocation id = data.readResourceLocation(); BlockPos pos = null; ItemStack stack = null; if (data.readBoolean()) { pos = data.readBlockPos(); } if (data.readBoolean()) { stack = data.readItem(); } PlayerSlot slot = new PlayerSlot(data); Pair grid = API.instance().getGridManager().createGrid(id, inv.player, stack, pos, slot); return new GridContainerMenu(grid.getLeft(), grid.getRight() instanceof BaseBlockEntity ? (BaseBlockEntity) grid.getRight() : null, inv.player, windowId); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/GridMenuProvider.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.screen.EmptyScreenInfoProvider; import com.refinedmods.refinedstorage.blockentity.BaseBlockEntity; import net.minecraft.network.chat.Component; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; public class GridMenuProvider implements MenuProvider { private final IGrid grid; private final BlockEntity blockEntity; public GridMenuProvider(IGrid grid, BlockEntity blockEntity) { this.grid = grid; this.blockEntity = blockEntity; } @Override public Component getDisplayName() { return grid.getTitle(); } @Nullable @Override public AbstractContainerMenu createMenu(int windowId, Inventory inv, Player player) { GridContainerMenu c = new GridContainerMenu(grid, blockEntity instanceof BaseBlockEntity ? (BaseBlockEntity) blockEntity : null, player, windowId); c.setScreenInfoProvider(new EmptyScreenInfoProvider()); c.initSlots(); return c; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/factory/WirelessCraftingMonitorContainerFactory.java ================================================ package com.refinedmods.refinedstorage.container.factory; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.IContainerFactory; public class WirelessCraftingMonitorContainerFactory implements IContainerFactory { @Override public CraftingMonitorContainerMenu create(int windowId, Inventory inv, FriendlyByteBuf data) { PlayerSlot slot = new PlayerSlot(data); ItemStack stack = slot.getStackFromSlot(inv.player); WirelessCraftingMonitor wirelessCraftingMonitor = new WirelessCraftingMonitor(stack, null, slot); return new CraftingMonitorContainerMenu(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), wirelessCraftingMonitor, null, inv.player, windowId); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/BaseSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot; import java.util.function.BooleanSupplier; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.SlotItemHandler; public class BaseSlot extends SlotItemHandler { private BooleanSupplier enableHandler = () -> true; public BaseSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y) { super(itemHandler, inventoryIndex, x, y); } public BaseSlot setEnableHandler(BooleanSupplier enableHandler) { this.enableHandler = enableHandler; return this; } @Override public boolean isActive() { return enableHandler.getAsBoolean(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/CrafterManagerSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode; import com.refinedmods.refinedstorage.screen.IScreenInfoProvider; import net.neoforged.neoforge.items.IItemHandler; public class CrafterManagerSlot extends BaseSlot { private final boolean visible; private final CrafterManagerNetworkNode crafterManager; private final IScreenInfoProvider display; public CrafterManagerSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y, boolean visible, IScreenInfoProvider display, CrafterManagerNetworkNode crafterManager) { super(itemHandler, inventoryIndex, x, y); this.visible = visible; this.display = display; this.crafterManager = crafterManager; } @Override public boolean isActive() { return y >= display.getTopHeight() && y < display.getTopHeight() + 18 * display.getVisibleRows() && visible && crafterManager.isActiveOnClient(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/DisabledSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nonnull; public class DisabledSlot extends BaseSlot { public DisabledSlot(IItemHandler itemHandler, int inventoryIndex, int x, int y) { super(itemHandler, inventoryIndex, x, y); } @Override public boolean mayPlace(@Nonnull ItemStack stack) { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/OutputSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nonnull; public class OutputSlot extends BaseSlot { public OutputSlot(IItemHandler inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } @Override public boolean mayPlace(@Nonnull ItemStack stack) { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/filter/DisabledFluidFilterSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.filter; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; public class DisabledFluidFilterSlot extends FluidFilterSlot { public DisabledFluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y, int flags) { super(inventory, inventoryIndex, x, y, flags); } public DisabledFluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } @Override public void onContainerClicked(@Nonnull ItemStack stack) { // NO OP } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/filter/FilterSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.filter; import com.refinedmods.refinedstorage.container.slot.BaseSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nonnull; public class FilterSlot extends BaseSlot { public static final int FILTER_ALLOW_SIZE = 1; public static final int FILTER_ALLOW_BLOCKS = 2; public static final int FILTER_ALLOW_ALTERNATIVES = 4; private final int flags; public FilterSlot(IItemHandler handler, int inventoryIndex, int x, int y, int flags) { super(handler, inventoryIndex, x, y); this.flags = flags; } public FilterSlot(IItemHandler handler, int inventoryIndex, int x, int y) { this(handler, inventoryIndex, x, y, 0); } @Override public boolean mayPlace(@Nonnull ItemStack stack) { if (super.mayPlace(stack)) { if (isBlockAllowed()) { return stack.getItem() instanceof BlockItem; } return true; } return false; } @Override public void set(@Nonnull ItemStack stack) { if (!stack.isEmpty() && !isSizeAllowed()) { stack.setCount(1); } super.set(stack); } @Override public boolean mayPickup(Player playerIn) { return false; } public boolean isSizeAllowed() { return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE; } public boolean isBlockAllowed() { return (flags & FILTER_ALLOW_BLOCKS) == FILTER_ALLOW_BLOCKS; } public boolean isAlternativesAllowed() { return (flags & FILTER_ALLOW_ALTERNATIVES) == FILTER_ALLOW_ALTERNATIVES; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/filter/FluidFilterSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.filter; import com.refinedmods.refinedstorage.container.slot.BaseSlot; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemStackHandler; import javax.annotation.Nonnull; public class FluidFilterSlot extends BaseSlot { public static final int FILTER_ALLOW_SIZE = 1; public static final int FILTER_ALLOW_ALTERNATIVES = 2; private final int flags; private final FluidInventory fluidInventory; public FluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y, int flags) { super(new ItemStackHandler(inventory.getSlots()), inventoryIndex, x, y); this.flags = flags; this.fluidInventory = inventory; } public FluidFilterSlot(FluidInventory inventory, int inventoryIndex, int x, int y) { this(inventory, inventoryIndex, x, y, 0); } @Override public boolean mayPlace(@Nonnull ItemStack stack) { return false; } public void onContainerClicked(@Nonnull ItemStack stack) { fluidInventory.setFluid(getSlotIndex(), StackUtils.getFluid(stack, true).getValue()); } @Override public boolean mayPickup(Player playerIn) { return false; } public boolean isSizeAllowed() { return (flags & FILTER_ALLOW_SIZE) == FILTER_ALLOW_SIZE; } public boolean isAlternativesAllowed() { return (flags & FILTER_ALLOW_ALTERNATIVES) == FILTER_ALLOW_ALTERNATIVES; } public FluidInventory getFluidInventory() { return fluidInventory; } // not overriding getHasStack as we do the tooltips ourselves public boolean hasStack() { return !fluidInventory.getFluid(getSlotIndex()).isEmpty(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/grid/CraftingGridSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.grid; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; public class CraftingGridSlot extends Slot { public CraftingGridSlot(Container inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/grid/ResultCraftingGridSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.grid; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.ResultSlot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.common.CommonHooks; import net.neoforged.neoforge.event.EventHooks; import javax.annotation.Nonnull; public class ResultCraftingGridSlot extends ResultSlot { private final IGrid grid; public ResultCraftingGridSlot(Player player, IGrid grid, int inventoryIndex, int x, int y) { super(player, grid.getCraftingMatrix(), grid.getCraftingResult(), inventoryIndex, x, y); this.grid = grid; } // @Volatile: Overriding logic from the super onTake method for Grid behaviors like refilling stacks from the network @Override public void onTake(Player player, @Nonnull ItemStack stack) { checkTakeAchievements(stack); CommonHooks.setCraftingPlayer(player); if (!player.getCommandSenderWorld().isClientSide) { grid.onCrafted(player, null, null); } EventHooks.firePlayerCraftingEvent(player, stack.copy(), grid.getCraftingMatrix()); CommonHooks.setCraftingPlayer(null); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyBaseSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.legacy; import net.minecraft.world.Container; import net.minecraft.world.inventory.Slot; import java.util.function.BooleanSupplier; public class LegacyBaseSlot extends Slot { private BooleanSupplier enableHandler = () -> true; public LegacyBaseSlot(Container inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } public LegacyBaseSlot setEnableHandler(BooleanSupplier enableHandler) { this.enableHandler = enableHandler; return this; } @Override public boolean isActive() { return enableHandler.getAsBoolean(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyDisabledSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.legacy; import net.minecraft.world.Container; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; public class LegacyDisabledSlot extends LegacyBaseSlot { public LegacyDisabledSlot(Container inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } @Override public boolean mayPlace(@Nonnull ItemStack stack) { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/slot/legacy/LegacyFilterSlot.java ================================================ package com.refinedmods.refinedstorage.container.slot.legacy; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; public class LegacyFilterSlot extends LegacyBaseSlot { public LegacyFilterSlot(Container inventory, int inventoryIndex, int x, int y) { super(inventory, inventoryIndex, x, y); } @Override public boolean mayPickup(Player player) { return false; } @Override public boolean mayPlace(ItemStack stack) { return true; } @Override public void set(@Nonnull ItemStack stack) { if (!stack.isEmpty()) { stack.setCount(1); } super.set(stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/FilterInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import java.util.function.Supplier; class FilterInventoryWrapper implements IInventoryWrapper { private final ItemFilterInventoryWrapper item; private final FluidFilterInventoryWrapper fluid; private final Supplier typeGetter; FilterInventoryWrapper(IItemHandlerModifiable itemTo, FluidInventory fluidTo, Supplier typeGetter) { this.item = new ItemFilterInventoryWrapper(itemTo); this.fluid = new FluidFilterInventoryWrapper(fluidTo); this.typeGetter = typeGetter; } @Override public InsertionResult insert(ItemStack stack) { return typeGetter.get() == IType.ITEMS ? item.insert(stack) : fluid.insert(stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/FluidFilterInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; class FluidFilterInventoryWrapper implements IInventoryWrapper { private final FluidInventory filterInv; FluidFilterInventoryWrapper(FluidInventory filterInv) { this.filterInv = filterInv; } @Override public InsertionResult insert(ItemStack stack) { InsertionResult stop = new InsertionResult(InsertionResultType.STOP); FluidStack fluidInContainer = StackUtils.getFluid(stack, true).getValue(); if (fluidInContainer.isEmpty()) { return stop; } for (FluidStack fluid : filterInv.getFluids()) { if (API.instance().getComparer().isEqual(fluidInContainer, fluid, IComparer.COMPARE_NBT)) { return stop; } } for (int i = 0; i < filterInv.getSlots(); ++i) { if (filterInv.getFluid(i).isEmpty()) { filterInv.setFluid(i, StackUtils.copy(fluidInContainer, FluidType.BUCKET_VOLUME)); return stop; } } return stop; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/IInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import net.minecraft.world.item.ItemStack; interface IInventoryWrapper { InsertionResult insert(ItemStack stack); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/InsertionResult.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import net.minecraft.world.item.ItemStack; class InsertionResult { private final InsertionResultType type; private ItemStack value; InsertionResult(ItemStack value) { this.type = InsertionResultType.CONTINUE_IF_POSSIBLE; this.value = value; } InsertionResult(InsertionResultType type) { this.type = type; } public InsertionResultType getType() { return type; } public ItemStack getValue() { return value; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/InsertionResultType.java ================================================ package com.refinedmods.refinedstorage.container.transfer; enum InsertionResultType { CONTINUE_IF_POSSIBLE, STOP } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/InventoryInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import net.minecraft.world.Container; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemHandlerHelper; import net.neoforged.neoforge.items.wrapper.InvWrapper; import net.neoforged.neoforge.items.wrapper.RangedWrapper; import java.util.Objects; class InventoryInventoryWrapper implements IInventoryWrapper { private final Container inventory; private final IItemHandler wrapper; InventoryInventoryWrapper(Container inventory) { this.inventory = inventory; if (inventory instanceof Inventory) { // Don't use PlayerMainInvWrapper to avoid stack animations. this.wrapper = new RangedWrapper(new InvWrapper(inventory), 0, ((Inventory) inventory).items.size()); } else { this.wrapper = new InvWrapper(inventory); } } @Override public InsertionResult insert(ItemStack stack) { return new InsertionResult(ItemHandlerHelper.insertItem(wrapper, stack, false)); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } InventoryInventoryWrapper that = (InventoryInventoryWrapper) o; return Objects.equals(inventory, that.inventory); } @Override public int hashCode() { return Objects.hash(inventory); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/ItemFilterInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.ItemHandlerHelper; class ItemFilterInventoryWrapper implements IInventoryWrapper { private final IItemHandlerModifiable filterInv; ItemFilterInventoryWrapper(IItemHandlerModifiable filterInv) { this.filterInv = filterInv; } @Override public InsertionResult insert(ItemStack stack) { InsertionResult stop = new InsertionResult(InsertionResultType.STOP); for (int i = 0; i < filterInv.getSlots(); ++i) { if (API.instance().getComparer().isEqualNoQuantity(filterInv.getStackInSlot(i), stack)) { return stop; } } for (int i = 0; i < filterInv.getSlots(); ++i) { if (filterInv.getStackInSlot(i).isEmpty()) { filterInv.setStackInSlot(i, ItemHandlerHelper.copyStackWithSize(stack, 1)); break; } } return stop; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/ItemHandlerInventoryWrapper.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.ItemHandlerHelper; import java.util.Objects; class ItemHandlerInventoryWrapper implements IInventoryWrapper { private final IItemHandler handler; ItemHandlerInventoryWrapper(IItemHandler handler) { this.handler = handler; } @Override public InsertionResult insert(ItemStack stack) { return new InsertionResult(ItemHandlerHelper.insertItem(handler, stack, false)); } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } ItemHandlerInventoryWrapper that = (ItemHandlerInventoryWrapper) o; return Objects.equals(handler, that.handler); } @Override public int hashCode() { return Objects.hash(handler); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/container/transfer/TransferManager.java ================================================ package com.refinedmods.refinedstorage.container.transfer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import net.minecraft.world.Container; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.SlotItemHandler; import javax.annotation.Nullable; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; public class TransferManager { private final Map> fromToMap = new HashMap<>(); private final AbstractContainerMenu container; @Nullable private Function notFoundHandler; public TransferManager(AbstractContainerMenu container) { this.container = container; } public void clearTransfers() { this.fromToMap.clear(); } public void setNotFoundHandler(@Nullable Function handler) { this.notFoundHandler = handler; } public void addTransfer(Container from, IItemHandler to) { addTransfer(new InventoryInventoryWrapper(from), new ItemHandlerInventoryWrapper(to)); } public void addTransfer(Container from, Container to) { addTransfer(new InventoryInventoryWrapper(from), new InventoryInventoryWrapper(to)); } public void addFilterTransfer(Container from, IItemHandlerModifiable itemTo, FluidInventory fluidTo, Supplier typeGetter) { addTransfer(new InventoryInventoryWrapper(from), new FilterInventoryWrapper(itemTo, fluidTo, typeGetter)); } public void addItemFilterTransfer(Container from, IItemHandlerModifiable to) { addTransfer(new InventoryInventoryWrapper(from), new ItemFilterInventoryWrapper(to)); } public void addFluidFilterTransfer(Container from, FluidInventory to) { addTransfer(new InventoryInventoryWrapper(from), new FluidFilterInventoryWrapper(to)); } public void addTransfer(IItemHandler from, Container to) { addTransfer(new ItemHandlerInventoryWrapper(from), new InventoryInventoryWrapper(to)); } public void addBiTransfer(Container from, IItemHandler to) { addTransfer(from, to); addTransfer(to, from); } private void addTransfer(IInventoryWrapper from, IInventoryWrapper to) { List toList = fromToMap.computeIfAbsent(from, k -> new LinkedList<>()); toList.add(to); } public ItemStack transfer(int index) { Slot slot = container.getSlot(index); IInventoryWrapper key; if (slot instanceof SlotItemHandler) { key = new ItemHandlerInventoryWrapper(((SlotItemHandler) slot).getItemHandler()); } else { key = new InventoryInventoryWrapper(slot.container); } List toList = fromToMap.get(key); if (toList != null) { ItemStack initial = slot.getItem().copy(); ItemStack remainder = slot.getItem(); for (IInventoryWrapper to : toList) { InsertionResult result = to.insert(remainder); if (result.getType() == InsertionResultType.STOP) { break; } else if (result.getType() == InsertionResultType.CONTINUE_IF_POSSIBLE) { remainder = result.getValue(); if (remainder.isEmpty()) { break; } } } slot.set(remainder); slot.setChanged(); if (API.instance().getComparer().isEqual(remainder, initial) && notFoundHandler != null) { return notFoundHandler.apply(index); } } else if (notFoundHandler != null) { return notFoundHandler.apply(index); } return ItemStack.EMPTY; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/BlockEntityTagGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RSBlockEntities; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.level.block.entity.BlockEntityType; import net.neoforged.neoforge.common.data.ExistingFileHelper; import java.util.concurrent.CompletableFuture; public class BlockEntityTagGenerator extends TagsProvider> { public BlockEntityTagGenerator(PackOutput output, String modId, CompletableFuture provider, ExistingFileHelper existingFileHelper) { super(output, Registries.BLOCK_ENTITY_TYPE, provider, modId, existingFileHelper); } @Override protected void addTags(HolderLookup.Provider provider) { TagAppender> packingTapeBlacklist = tag( TagKey.create(Registries.BLOCK_ENTITY_TYPE, new ResourceLocation("packingtape:blacklist/problematic")) ); packingTapeBlacklist.add( resourceKey(RSBlockEntities.CONTROLLER.get()), resourceKey(RSBlockEntities.CREATIVE_CONTROLLER.get()), resourceKey(RSBlockEntities.DETECTOR.get()), resourceKey(RSBlockEntities.DISK_DRIVE.get()), resourceKey(RSBlockEntities.EXPORTER.get()), resourceKey(RSBlockEntities.EXTERNAL_STORAGE.get()), resourceKey(RSBlockEntities.GRID.get()), resourceKey(RSBlockEntities.CRAFTING_GRID.get()), resourceKey(RSBlockEntities.PATTERN_GRID.get()), resourceKey(RSBlockEntities.FLUID_GRID.get()), resourceKey(RSBlockEntities.IMPORTER.get()), resourceKey(RSBlockEntities.NETWORK_TRANSMITTER.get()), resourceKey(RSBlockEntities.NETWORK_RECEIVER.get()), resourceKey(RSBlockEntities.RELAY.get()), resourceKey(RSBlockEntities.CABLE.get()), resourceKey(RSBlockEntities.ONE_K_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.FOUR_K_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.SIXTEEN_K_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.SIXTY_FOUR_K_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.CREATIVE_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.CREATIVE_FLUID_STORAGE_BLOCK.get()), resourceKey(RSBlockEntities.SECURITY_MANAGER.get()), resourceKey(RSBlockEntities.INTERFACE.get()), resourceKey(RSBlockEntities.FLUID_INTERFACE.get()), resourceKey(RSBlockEntities.WIRELESS_TRANSMITTER.get()), resourceKey(RSBlockEntities.STORAGE_MONITOR.get()), resourceKey(RSBlockEntities.CONSTRUCTOR.get()), resourceKey(RSBlockEntities.DESTRUCTOR.get()), resourceKey(RSBlockEntities.DISK_MANIPULATOR.get()), resourceKey(RSBlockEntities.PORTABLE_GRID.get()), resourceKey(RSBlockEntities.CREATIVE_PORTABLE_GRID.get()), resourceKey(RSBlockEntities.CRAFTER.get()), resourceKey(RSBlockEntities.CRAFTER_MANAGER.get()), resourceKey(RSBlockEntities.CRAFTING_MONITOR.get()) ); } private ResourceKey> resourceKey(BlockEntityType type) { return BuiltInRegistries.BLOCK_ENTITY_TYPE.getResourceKey(type).get(); } @Override public String getName() { return "Block Entity Type Tags"; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/BlockModelGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.block.ControllerBlock; import com.refinedmods.refinedstorage.block.DetectorBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.util.BlockColorMap; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.client.model.generators.BlockStateProvider; import net.neoforged.neoforge.client.model.generators.ModelFile; import net.neoforged.neoforge.common.data.ExistingFileHelper; public class BlockModelGenerator extends BlockStateProvider { private static final ResourceLocation BOTTOM = new ResourceLocation(RS.ID, "block/bottom"); private final BlockModels models; public BlockModelGenerator(PackOutput output, String id, ExistingFileHelper existingFileHelper) { super(output, id, existingFileHelper); models = new BlockModels(this); } @Override protected void registerStatesAndModels() { genNorthCutoutModels(RSBlocks.GRID, false); genNorthCutoutModels(RSBlocks.CRAFTING_GRID, false); genNorthCutoutModels(RSBlocks.PATTERN_GRID, false); genNorthCutoutModels(RSBlocks.FLUID_GRID, false); genNorthCutoutModels(RSBlocks.CRAFTING_MONITOR, false); genNorthCutoutModels(RSBlocks.CRAFTER_MANAGER, false); genNorthCutoutModels(RSBlocks.DISK_MANIPULATOR, true); genControllerModels(RSBlocks.CONTROLLER); genControllerModels(RSBlocks.CREATIVE_CONTROLLER); genCrafterModels(); genCubeAllCutoutModels(RSBlocks.RELAY); genCubeAllCutoutModels(RSBlocks.NETWORK_TRANSMITTER); genCubeAllCutoutModels(RSBlocks.NETWORK_RECEIVER); genSecurityManagerModels(); genDetectorModels(); genWirelessTransmitterModels(); } private void genWirelessTransmitterModels() { RSBlocks.WIRELESS_TRANSMITTER.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = RSBlocks.WIRELESS_TRANSMITTER.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.wirelessTransmitterBlock(block, state -> { if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) { return models.createWirelessTransmitterNonEmissiveModel( "block/" + folderName + "/disconnected", resourceLocation(folderName, "cutouts/disconnected") ); } else { ModelFile model = models.createWirelessTransmitterModel( "block/" + folderName + "/" + color, resourceLocation(folderName, "cutouts/" + color) ); simpleBlockItem(block, model); return model; } }, 0); }); } private void genDetectorModels() { RSBlocks.DETECTOR.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = RSBlocks.DETECTOR.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.simpleBlockStateModel(block, state -> { if (Boolean.FALSE.equals(state.getValue(DetectorBlock.POWERED))) { return models.createDetectorNonEmissiveModel( "block/" + folderName + "/off", resourceLocation(folderName, "cutouts/off") ); } else { ModelFile model = models.createDetectorModel( "block/" + folderName + "/" + color, resourceLocation(folderName, "cutouts/" + color) ); simpleBlockItem(block, model); return model; } }); }); } private void genSecurityManagerModels() { RSBlocks.SECURITY_MANAGER.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = RSBlocks.SECURITY_MANAGER.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.horizontalRSBlock(block, state -> { if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) { return models.createCubeCutoutNonEmissiveModel( "block/" + folderName + "/disconnected", BOTTOM, BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "cutouts/top_disconnected"), resourceLocation(folderName, "right"), resourceLocation(folderName, "cutouts/right_disconnected"), resourceLocation(folderName, "left"), resourceLocation(folderName, "cutouts/left_disconnected"), resourceLocation(folderName, "front"), resourceLocation(folderName, "cutouts/front_disconnected"), resourceLocation(folderName, "back"), resourceLocation(folderName, "cutouts/back_disconnected") ); } else { ModelFile model = models.createCubeCutoutModel( "block/" + folderName + "/" + color, BOTTOM, BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "cutouts/top" + "_" + color), resourceLocation(folderName, "right"), resourceLocation(folderName, "cutouts/right" + "_" + color), resourceLocation(folderName, "left"), resourceLocation(folderName, "cutouts/left" + "_" + color), resourceLocation(folderName, "front"), resourceLocation(folderName, "cutouts/front" + "_" + color), resourceLocation(folderName, "back"), resourceLocation(folderName, "cutouts/back" + "_" + color) ); simpleBlockItem(block, model); return model; } }, 180); }); } private void genCubeAllCutoutModels(BlockColorMap blockMap) { blockMap.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = blockMap.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.simpleBlockStateModel(block, state -> { if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) { return models.createCubeAllCutoutNonEmissiveModel( "block/" + folderName + "/disconnected", resourceLocation(folderName, folderName), resourceLocation(folderName, folderName), resourceLocation(folderName, "cutouts/disconnected") ); } else { ModelFile model = models.createCubeAllCutoutModel( "block/" + folderName + "/" + color, resourceLocation(folderName, folderName), resourceLocation(folderName, folderName), resourceLocation(folderName, "cutouts/" + color) ); simpleBlockItem(block, model); return model; } }); }); } private void genCrafterModels() { RSBlocks.CRAFTER.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = RSBlocks.CRAFTER.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.anyDirectionalRSBlock(block, state -> { if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) { return models.createCubeCutoutNonEmissiveModel( "block/" + folderName + "/disconnected", BOTTOM, BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "cutouts/top_disconnected"), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_disconnected"), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_disconnected"), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_disconnected"), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_disconnected") ); } else { ModelFile model = models.createCubeCutoutModel( "block/" + folderName + "/" + color, BOTTOM, BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "cutouts/top_" + color), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_" + color), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_" + color), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_" + color), resourceLocation(folderName, "side"), resourceLocation(folderName, "cutouts/side_" + color) ); simpleBlockItem(block, model); return model; } }, 180); }); } private void genControllerModels(BlockColorMap blockMap) { blockMap.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = RSBlocks.CONTROLLER.get(ColorMap.DEFAULT_COLOR).getId().getPath(); models.simpleBlockStateModel(block, state -> { if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.OFF)) { return models.createCubeAllCutoutNonEmissiveModel( "block/" + folderName + "/off", resourceLocation(folderName, "off"), resourceLocation(folderName, "off"), resourceLocation(folderName, "cutouts/off") ); } else if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.NEARLY_OFF)) { return models.createControllerNearlyCutoutModel( "block/" + folderName + "/nearly_off", resourceLocation(folderName, "off"), resourceLocation(folderName, "on"), resourceLocation(folderName, "cutouts/nearly_off"), resourceLocation(folderName, "cutouts/nearly_off_gray") ); } else if (state.getValue(ControllerBlock.ENERGY_TYPE).equals(ControllerBlock.EnergyType.NEARLY_ON)) { return models.createControllerNearlyCutoutModel( "block/" + folderName + "/nearly_on", resourceLocation(folderName, "off"), resourceLocation(folderName, "on"), resourceLocation(folderName, "cutouts/nearly_on"), resourceLocation(folderName, "cutouts/nearly_on_gray") ); } else { ModelFile model = models.createCubeAllCutoutModel( "block/" + folderName + "/" + color, resourceLocation(folderName, "off"), resourceLocation(folderName, "on"), resourceLocation(folderName, "cutouts/" + color) ); final ResourceLocation energyType = new ResourceLocation(RS.ID, "energy_type"); itemModels().getBuilder(BuiltInRegistries.BLOCK.getKey(block).getPath()) .override() .predicate(energyType, 0) .model(models().getExistingFile( new ResourceLocation(RS.ID, "block/" + folderName + "/off") )).end().override() .predicate(energyType, 1) .model(models().getExistingFile( new ResourceLocation(RS.ID, "block/" + folderName + "/nearly_off") )).end().override() .predicate(energyType, 2) .model(models().getExistingFile( new ResourceLocation(RS.ID, "block/" + folderName + "/nearly_on") )).end().override() .predicate(energyType, 3) .model(model).end(); return model; } }); }); } private void genNorthCutoutModels(BlockColorMap blockMap, boolean useLoader) { blockMap.forEach((color, registryObject) -> { Block block = registryObject.get(); String folderName = blockMap.get(ColorMap.DEFAULT_COLOR).getId().getPath(); ModelFile disconnected = models.createCubeNorthCutoutNonEmissiveModel( "block/" + folderName + "/disconnected", BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "front"), resourceLocation(folderName, "back"), resourceLocation(folderName, "right"), resourceLocation(folderName, "left"), resourceLocation(folderName, "right"), resourceLocation(folderName, "cutouts/disconnected") ); ModelFile connected = models.createCubeNorthCutoutModel( "block/" + folderName + "/" + color, BOTTOM, resourceLocation(folderName, "top"), resourceLocation(folderName, "front"), resourceLocation(folderName, "back"), resourceLocation(folderName, "right"), resourceLocation(folderName, "left"), resourceLocation(folderName, "right"), resourceLocation(folderName, "cutouts/" + color) ); //generate Item Model simpleBlockItem(block, connected); if (useLoader) { models.customLoaderRSBlock(block, resourceLocation(folderName, "loader"), connected, disconnected); } else { models.horizontalRSBlock(block, state -> { if (Boolean.FALSE.equals(state.getValue(NetworkNodeBlock.CONNECTED))) { return disconnected; } else { return connected; } }, 180); } }); } private ResourceLocation resourceLocation(String folderName, String name) { return new ResourceLocation(RS.ID, "block/" + folderName + "/" + name); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/BlockModels.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.block.BlockDirection; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.generators.BlockModelBuilder; import net.neoforged.neoforge.client.model.generators.ConfiguredModel; import net.neoforged.neoforge.client.model.generators.CustomLoaderBuilder; import net.neoforged.neoforge.client.model.generators.ModelFile; import net.neoforged.neoforge.common.data.ExistingFileHelper; import java.util.function.Function; public class BlockModels { private final BlockModelGenerator generator; public BlockModels(BlockModelGenerator blockModelGenerator) { this.generator = blockModelGenerator; } public void simpleBlockStateModel(Block block, Function model) { generator.getVariantBuilder(block).forAllStates(state -> ConfiguredModel.builder().modelFile(model.apply(state)).build()); } public void anyDirectionalRSBlock(Block block, Function modelFunc, int angleOffset) { generator.getVariantBuilder(block) .forAllStates(state -> { Direction dir = state.getValue(BlockDirection.ANY.getProperty()); int xRotation = 0; if (dir == Direction.DOWN) { xRotation = 180; } if (dir.getAxis().isHorizontal()) { xRotation = 90; } return ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationX(xRotation) .rotationY(dir.getAxis().isVertical() ? 0 : (((int) dir.toYRot()) + angleOffset) % 360) .build(); }); } public void wirelessTransmitterBlock(Block block, Function modelFunc, int angleOffset) { generator.getVariantBuilder(block) .forAllStates(state -> { Direction dir = state.getValue(BlockDirection.ANY.getProperty()); int xRotation; if (dir.getAxis() == Direction.Axis.Y) { xRotation = dir == Direction.UP ? 180 : 0; } else { xRotation = dir.getAxis().isHorizontal() ? 90 : 0; } return ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationX(xRotation) .rotationY(dir.getAxis().isVertical() ? 0 : (((int) dir.toYRot()) + angleOffset) % 360) .build(); }); } public void horizontalRSBlock(Block block, Function modelFunc, int angleOffset) { generator.getVariantBuilder(block) .forAllStates(state -> ConfiguredModel.builder() .modelFile(modelFunc.apply(state)) .rotationY(((int) state.getValue(BlockDirection.HORIZONTAL.getProperty()).toYRot() + angleOffset) % 360) .build() ); } public void customLoaderRSBlock(Block block, ResourceLocation path, ModelFile connectedModel, ModelFile disconnectedModel) { var model = generator.models().getBuilder(path.toString()) .renderType("cutout").customLoader((builder, filehelper) -> new CustomLoaderBuilderBasic(new ResourceLocation(RS.ID, "disk_manipulator"), builder, filehelper)).end(); generator.getVariantBuilder(block).setModels(generator.getVariantBuilder(block).partialState(), ConfiguredModel.builder().modelFile(model).buildLast()); } public BlockModelBuilder createDetectorModel(String name, ResourceLocation torch) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "detector")) .texture("torch", torch); } public BlockModelBuilder createDetectorNonEmissiveModel(String name, ResourceLocation torch) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "detector_nonemissive")) .texture("torch", torch); } public BlockModelBuilder createWirelessTransmitterModel(String name, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "wireless_transmitter")) .texture("cutout", cutout); } public BlockModelBuilder createWirelessTransmitterNonEmissiveModel(String name, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "wireless_transmitter_nonemissive")) .texture("cutout", cutout); } 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) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_cutout")) .texture("particle", north) .texture("east", east) .texture("south", south) .texture("west", west) .texture("up", up) .texture("down", down) .texture("north", north) .texture("cutout_down", downCutout) .texture("cutout_east", eastCutout) .texture("cutout_west", westCutout) .texture("cutout_south", southCutout) .texture("cutout_north", northCutout) .texture("cutout_up", upCutout); } 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) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_cutout_nonemissive")) .texture("particle", north) .texture("east", east) .texture("south", south) .texture("west", west) .texture("up", up) .texture("down", down) .texture("north", north) .texture("cutout_down", downCutout) .texture("cutout_east", eastCutout) .texture("cutout_west", westCutout) .texture("cutout_south", southCutout) .texture("cutout_north", northCutout) .texture("cutout_up", upCutout); } public BlockModelBuilder createControllerNearlyCutoutModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation grayCutout, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "block/controller_nearly")) .texture("particle", particle) .texture("all", all) .texture("cutout_gray", grayCutout) .texture("cutout", cutout); } public BlockModelBuilder createCubeAllCutoutModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_all_cutout")) .texture("particle", particle) .texture("all", all) .texture("cutout", cutout); } public BlockModelBuilder createCubeAllCutoutNonEmissiveModel(String name, ResourceLocation particle, ResourceLocation all, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_all_cutout_nonemissive")) .texture("particle", particle) .texture("all", all) .texture("cutout", cutout); } public BlockModelBuilder createCubeNorthCutoutModel(String name, ResourceLocation down, ResourceLocation up, ResourceLocation north, ResourceLocation south, ResourceLocation east, ResourceLocation west, ResourceLocation particle, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_north_cutout")) .texture("particle", particle) .texture("east", east) .texture("south", south) .texture("west", west) .texture("up", up) .texture("down", down) .texture("north", north) .texture("cutout", cutout); } public BlockModelBuilder createCubeNorthCutoutNonEmissiveModel(String name, ResourceLocation down, ResourceLocation up, ResourceLocation north, ResourceLocation south, ResourceLocation east, ResourceLocation west, ResourceLocation particle, ResourceLocation cutout) { return generator.models().withExistingParent(name, new ResourceLocation(RS.ID, "cube_north_cutout_nonemissive")) .texture("particle", particle) .texture("east", east) .texture("south", south) .texture("west", west) .texture("up", up) .texture("down", down) .texture("north", north) .texture("cutout", cutout); } class CustomLoaderBuilderBasic extends CustomLoaderBuilder { protected CustomLoaderBuilderBasic(ResourceLocation loaderId, BlockModelBuilder parent, ExistingFileHelper existingFileHelper) { super(loaderId, parent, existingFileHelper); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/BlockTagGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RSBlocks; import net.minecraft.core.HolderLookup; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.data.PackOutput; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.BlockTags; import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.common.data.BlockTagsProvider; import net.neoforged.neoforge.common.data.ExistingFileHelper; import javax.annotation.Nullable; import java.util.concurrent.CompletableFuture; public class BlockTagGenerator extends BlockTagsProvider { public BlockTagGenerator(PackOutput output, CompletableFuture lookupProvider, String modId, @Nullable ExistingFileHelper existingFileHelper) { super(output, lookupProvider, modId, existingFileHelper); } @Override protected void addTags(HolderLookup.Provider provider) { TagAppender noRelocationTag = tag(BlockTags.create(new ResourceLocation("forge:relocation_not_supported"))); RSBlocks.COLORED_BLOCK_TAGS.forEach((tag, map) -> { map.values().forEach(block -> tag(tag).add(block.get())); noRelocationTag.addTags(tag); }); RSBlocks.STORAGE_BLOCKS.forEach((tag, block) -> noRelocationTag.add(resourceKey(block.get()))); RSBlocks.FLUID_STORAGE_BLOCKS.forEach((tag, block) -> noRelocationTag.add(resourceKey(block.get()))); noRelocationTag.add( resourceKey(RSBlocks.IMPORTER.get()), resourceKey(RSBlocks.EXPORTER.get()), resourceKey(RSBlocks.EXTERNAL_STORAGE.get()), resourceKey(RSBlocks.DISK_DRIVE.get()), resourceKey(RSBlocks.INTERFACE.get()), resourceKey(RSBlocks.FLUID_INTERFACE.get()), resourceKey(RSBlocks.STORAGE_MONITOR.get()), resourceKey(RSBlocks.CONSTRUCTOR.get()), resourceKey(RSBlocks.DESTRUCTOR.get()), resourceKey(RSBlocks.PORTABLE_GRID.get()), resourceKey(RSBlocks.CREATIVE_PORTABLE_GRID.get()) ); } private ResourceKey resourceKey(Block block) { return BuiltInRegistries.BLOCK.getResourceKey(block).get(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/DataGenerators.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RS; import net.minecraft.data.loot.LootTableProvider; import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.common.data.BlockTagsProvider; import net.neoforged.neoforge.data.event.GatherDataEvent; import java.util.List; import java.util.Set; public class DataGenerators { @SubscribeEvent public void runDataGeneration(GatherDataEvent event) { event.getGenerator().addProvider(event.includeClient(), new BlockModelGenerator(event.getGenerator().getPackOutput(), RS.ID, event.getExistingFileHelper())); event.getGenerator().addProvider(event.includeServer(), new RecipeGenerator(event.getGenerator().getPackOutput())); BlockTagGenerator blockTagGenerator = new BlockTagGenerator( event.getGenerator().getPackOutput(), event.getLookupProvider(), RS.ID, event.getExistingFileHelper() ); final BlockTagsProvider blockTagsProvider = event.getGenerator().addProvider(event.includeServer(), blockTagGenerator); event.getGenerator().addProvider(event.includeServer(), new ItemTagGenerator( event.getGenerator().getPackOutput(), event.getLookupProvider(), blockTagsProvider.contentsGetter(), RS.ID, event.getExistingFileHelper() )); event.getGenerator().addProvider(event.includeServer(), new BlockEntityTagGenerator( event.getGenerator().getPackOutput(), RS.ID, event.getLookupProvider(), event.getExistingFileHelper() )); event.getGenerator().addProvider(event.includeServer(), new LootTableProvider( event.getGenerator().getPackOutput(), Set.of(), List.of(new LootTableProvider.SubProviderEntry( LootTableGenerator::new, LootContextParamSets.BLOCK )) )); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/ItemTagGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RSItems; import java.util.concurrent.CompletableFuture; import net.minecraft.core.HolderLookup; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.ItemTagsProvider; import net.minecraft.data.tags.TagsProvider; import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.common.data.ExistingFileHelper; public class ItemTagGenerator extends ItemTagsProvider { public ItemTagGenerator(PackOutput output, CompletableFuture lookup, CompletableFuture> p_275322_, String modId, ExistingFileHelper existingFileHelper) { super(output, lookup, p_275322_, modId, existingFileHelper); } @Override protected void addTags(HolderLookup.Provider provider) { RSItems.COLORED_ITEM_TAGS.forEach((tag, map) -> map.values().forEach(item -> tag(tag).add(item.get()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/LootTableGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.loottable.ControllerLootFunction; import com.refinedmods.refinedstorage.loottable.CrafterLootFunction; import net.minecraft.data.loot.BlockLootSubProvider; import net.minecraft.world.flag.FeatureFlags; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.storage.loot.LootPool; import net.minecraft.world.level.storage.loot.LootTable; import net.minecraft.world.level.storage.loot.entries.LootItem; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; import net.minecraft.world.level.storage.loot.predicates.ExplosionCondition; import net.minecraft.world.level.storage.loot.providers.number.ConstantValue; import net.neoforged.neoforge.registries.DeferredHolder; import java.util.Collections; import java.util.stream.Collectors; public class LootTableGenerator extends BlockLootSubProvider { public LootTableGenerator() { super(Collections.emptySet(), FeatureFlags.REGISTRY.allFlags()); } @Override protected void generate() { RSBlocks.CONTROLLER.values().forEach(block -> genBlockItemLootTableWithFunction(block.get(), ControllerLootFunction::new)); RSBlocks.CREATIVE_CONTROLLER.values().forEach(block -> dropSelf(block.get())); RSBlocks.CRAFTER.values().forEach(block -> genBlockItemLootTableWithFunction(block.get(), CrafterLootFunction::new)); RSBlocks.GRID.values().forEach(block -> dropSelf(block.get())); RSBlocks.CRAFTING_GRID.values().forEach(block -> dropSelf(block.get())); RSBlocks.FLUID_GRID.values().forEach(block -> dropSelf(block.get())); RSBlocks.PATTERN_GRID.values().forEach(block -> dropSelf(block.get())); RSBlocks.SECURITY_MANAGER.values().forEach(block -> dropSelf(block.get())); RSBlocks.WIRELESS_TRANSMITTER.values().forEach(block -> dropSelf(block.get())); RSBlocks.RELAY.values().forEach(block -> dropSelf(block.get())); RSBlocks.NETWORK_TRANSMITTER.values().forEach(block -> dropSelf(block.get())); RSBlocks.NETWORK_RECEIVER.values().forEach(block -> dropSelf(block.get())); RSBlocks.DISK_MANIPULATOR.values().forEach(block -> dropSelf(block.get())); RSBlocks.CRAFTING_MONITOR.values().forEach(block -> dropSelf(block.get())); RSBlocks.CRAFTER_MANAGER.values().forEach(block -> dropSelf(block.get())); RSBlocks.DETECTOR.values().forEach(block -> dropSelf(block.get())); } @Override protected Iterable getKnownBlocks() { return RSBlocks.COLORED_BLOCKS.stream().map(DeferredHolder::get).collect(Collectors.toList()); } private void genBlockItemLootTableWithFunction(Block block, LootItemFunction.Builder builder) { add(block, LootTable.lootTable().withPool( LootPool.lootPool() .setRolls(ConstantValue.exactly(1)) .add(LootItem.lootTableItem(block) .apply(builder)) .when(ExplosionCondition.survivesExplosion()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/datageneration/RecipeGenerator.java ================================================ package com.refinedmods.refinedstorage.datageneration; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.item.ProcessorItem; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.advancements.critereon.InventoryChangeTrigger; import net.minecraft.data.PackOutput; import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeOutput; import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.recipes.ShapelessRecipeBuilder; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.Items; public class RecipeGenerator extends RecipeProvider { private static final String GRID_ID = RS.ID + ":grid"; public RecipeGenerator(PackOutput output) { super(output); } @Override protected void buildRecipes(RecipeOutput output) { // Tag + Color -> Colored Block RSItems.COLORED_ITEM_TAGS.forEach((tag, map) -> map.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get()) .requires(tag) .requires(color.getTag()) .group(RS.ID) .unlockedBy("refinedstorage:controller", InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.CONTROLLER.get(ColorMap.DEFAULT_COLOR).get())) .save(output, new ResourceLocation(RS.ID, "coloring_recipes/" + item.getId().getPath())) )); // Crafting Grid RSItems.CRAFTING_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get()) .requires(RSItems.GRID.get(color).get()) .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get()) .requires(ItemTags.create(new ResourceLocation(RS.ID, "crafting_tables"))) .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get())) .save(output, new ResourceLocation(RS.ID, "crafting_grid/" + item.getId().getPath())) ); // Fluid Grid RSItems.FLUID_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get()) .requires(RSItems.GRID.get(color).get()) .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get()) .requires(Items.BUCKET) .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get())) .save(output, new ResourceLocation(RS.ID, "fluid_grid/" + item.getId().getPath())) ); // Pattern Grid RSItems.PATTERN_GRID.forEach((color, item) -> ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, item.get()) .requires(RSItems.GRID.get(color).get()) .requires(RSItems.PROCESSORS.get(ProcessorItem.Type.ADVANCED).get()) .requires(RSItems.PATTERN.get()) .unlockedBy(GRID_ID, InventoryChangeTrigger.TriggerInstance.hasItems(RSItems.GRID.get(ColorMap.DEFAULT_COLOR).get())) .save(output, new ResourceLocation(RS.ID, "pattern_grid/" + item.getId().getPath())) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/energy/BaseEnergyStorage.java ================================================ package com.refinedmods.refinedstorage.energy; import net.neoforged.neoforge.energy.EnergyStorage; public class BaseEnergyStorage extends EnergyStorage { public BaseEnergyStorage(int capacity, int maxReceive, int maxExtract) { super(capacity, maxReceive, maxExtract); } // @Volatile: Impl from EnergyStorage#extractEnergy, without the canExtract check public void extractEnergyBypassCanExtract(int maxExtract, boolean simulate) { int energyExtracted = Math.min(energy, maxExtract); if (!simulate) { energy -= energyExtracted; } } public void setStored(int energy) { this.energy = energy; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/energy/ItemEnergyStorage.java ================================================ package com.refinedmods.refinedstorage.energy; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.energy.EnergyStorage; public class ItemEnergyStorage extends EnergyStorage { private static final String NBT_ENERGY = "Energy"; private final ItemStack stack; public ItemEnergyStorage(ItemStack stack, int capacity) { super(capacity, Integer.MAX_VALUE, Integer.MAX_VALUE); this.stack = stack; this.energy = stack.hasTag() && stack.getTag().contains(NBT_ENERGY) ? stack.getTag().getInt(NBT_ENERGY) : 0; } @Override public int receiveEnergy(int maxReceive, boolean simulate) { int received = super.receiveEnergy(maxReceive, simulate); if (received > 0 && !simulate) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_ENERGY, getEnergyStored()); } return received; } @Override public int extractEnergy(int maxExtract, boolean simulate) { int extracted = super.extractEnergy(maxExtract, simulate); if (extracted > 0 && !simulate) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_ENERGY, getEnergyStored()); } return extracted; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/craftingtweaks/CraftingTweaksIntegration.java ================================================ package com.refinedmods.refinedstorage.integration.craftingtweaks; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.container.slot.grid.CraftingGridSlot; import net.minecraft.nbt.CompoundTag; import net.neoforged.fml.InterModComms; import net.neoforged.fml.ModList; import java.util.function.Function; import java.util.function.Predicate; public final class CraftingTweaksIntegration { private static final String ID = "craftingtweaks"; private CraftingTweaksIntegration() { } public static boolean isLoaded() { return ModList.get().isLoaded(ID); } public static boolean isCraftingTweaksClass(Class clazz) { return clazz.getName().startsWith("net.blay09.mods.craftingtweaks"); } public static void register() { CompoundTag tag = new CompoundTag(); tag.putString("ContainerClass", GridContainerMenu.class.getName()); tag.putString("ValidContainerPredicate", ValidContainerPredicate.class.getName()); tag.putString("GetGridStartFunction", GetGridStartFunction.class.getName()); tag.putString("AlignToGrid", "left"); InterModComms.sendTo(ID, "RegisterProvider", () -> tag); } public static class ValidContainerPredicate implements Predicate { @Override public boolean test(GridContainerMenu containerGrid) { return containerGrid.getGrid().getGridType() == GridType.CRAFTING; } } public static class GetGridStartFunction implements Function { @Override public Integer apply(GridContainerMenu containerGrid) { for (int i = 0; i < containerGrid.slots.size(); i++) { if (containerGrid.slots.get(i) instanceof CraftingGridSlot) { return i; } } return 0; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/curios/CuriosIntegration.java ================================================ package com.refinedmods.refinedstorage.integration.curios; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.InterModComms; import net.neoforged.fml.ModList; import net.neoforged.fml.event.lifecycle.InterModEnqueueEvent; import top.theillusivec4.curios.api.SlotTypeMessage; import top.theillusivec4.curios.api.SlotTypePreset; public class CuriosIntegration { private static final String ID = "curios"; public CuriosIntegration() { } public static boolean isLoaded() { return ModList.get().isLoaded(ID); } @SubscribeEvent public void registerSlots(InterModEnqueueEvent event) { InterModComms.sendTo(ID, SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.BELT.getMessageBuilder().build()); InterModComms.sendTo(ID, SlotTypeMessage.REGISTER_TYPE, () -> SlotTypePreset.BODY.getMessageBuilder().build()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/inventorysorter/InventorySorterIntegration.java ================================================ package com.refinedmods.refinedstorage.integration.inventorysorter; import com.refinedmods.refinedstorage.RS; import net.minecraft.resources.ResourceLocation; import net.neoforged.fml.InterModComms; import net.neoforged.fml.ModList; public class InventorySorterIntegration { private static final String ID = "inventorysorter"; private InventorySorterIntegration() { } public static boolean isLoaded() { return ModList.get().isLoaded(ID); } public static void register() { // Prevent items moving while scrolling through slots with Inventory Sorter in the Crafter Manager InterModComms.sendTo("inventorysorter", "slotblacklist", () -> "com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot"); InterModComms.sendTo("inventorysorter", "containerblacklist", () -> new ResourceLocation(RS.ID, "crafter")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/inventorytweaks/InventoryTweaksIntegration.java ================================================ package com.refinedmods.refinedstorage.integration.inventorytweaks; import net.neoforged.fml.ModList; public class InventoryTweaksIntegration { private InventoryTweaksIntegration() { } public static boolean isLoaded() { return ModList.get().isLoaded("inventorytweaks"); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/CoverCraftingCategoryExtension.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.item.CoverItem; import com.refinedmods.refinedstorage.recipe.CoverRecipe; import java.util.ArrayList; import java.util.Collections; import java.util.List; import com.google.common.collect.Streams; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.builder.IRecipeSlotBuilder; import mezz.jei.api.gui.ingredient.ICraftingGridHelper; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.category.extensions.vanilla.crafting.ICraftingCategoryExtension; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.common.Tags; public class CoverCraftingCategoryExtension implements ICraftingCategoryExtension { @Override public void setRecipe(RecipeHolder recipe, IRecipeLayoutBuilder builder, ICraftingGridHelper craftingGridHelper, IFocusGroup focuses) { List input = new ArrayList<>(); List output = new ArrayList<>(); for (Block block : BuiltInRegistries.BLOCK) { Item item = Item.BY_BLOCK.get(block); if (item == null || item == Items.AIR) { continue; } ItemStack itemStack = new ItemStack(item); if (CoverManager.isValidCover(itemStack)) { input.add(itemStack); ItemStack coverStack = new ItemStack(RSItems.COVER.get()); CoverItem.setItem(coverStack, itemStack); output.add(coverStack); } } final var nuggetTag = BuiltInRegistries.ITEM.getTagOrEmpty(Tags.Items.NUGGETS_IRON); List nuggets = Streams.stream(nuggetTag).map(ItemStack::new).toList(); List> inputs = new ArrayList<>(Collections.nCopies(9, new ArrayList<>())); inputs.set(3, nuggets); inputs.set(4, input); List inputSlots = craftingGridHelper.createAndSetInputs(builder, inputs, 3, 3); IRecipeSlotBuilder outputSlot = craftingGridHelper.createAndSetOutputs(builder, output); builder.createFocusLink(inputSlots.get(4), outputSlot); } @Override public int getWidth(RecipeHolder recipe) { return 3; } @Override public int getHeight(RecipeHolder recipe) { return 3; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/GhostIngredientHandler.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot; import com.refinedmods.refinedstorage.network.SetFilterSlotMessage; import com.refinedmods.refinedstorage.network.SetFluidFilterSlotMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.StackUtils; import mezz.jei.api.gui.handlers.IGhostIngredientHandler; import mezz.jei.api.ingredients.ITypedIngredient; import net.minecraft.client.renderer.Rect2i; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import java.util.ArrayList; import java.util.List; public class GhostIngredientHandler implements IGhostIngredientHandler { @Override public List> getTargetsTyped(BaseScreen gui, ITypedIngredient ingredient, boolean doStart) { List> targets = new ArrayList<>(); for (Slot slot : gui.getMenu().slots) { if (!slot.isActive()) { continue; } Rect2i bounds = new Rect2i(gui.getGuiLeft() + slot.x, gui.getGuiTop() + slot.y, 17, 17); if (ingredient.getIngredient() instanceof ItemStack && (slot instanceof LegacyFilterSlot || slot instanceof FilterSlot)) { targets.add(new Target() { @Override public Rect2i getArea() { return bounds; } @Override public void accept(I ingredient) { slot.set((ItemStack) ingredient); RS.NETWORK_HANDLER.sendToServer(new SetFilterSlotMessage(slot.index, (ItemStack) ingredient)); } }); } else if (ingredient instanceof FluidStack && slot instanceof FluidFilterSlot) { targets.add(new Target<>() { @Override public Rect2i getArea() { return bounds; } @Override public void accept(I ingredient) { RS.NETWORK_HANDLER.sendToServer(new SetFluidFilterSlotMessage(slot.index, StackUtils.copy((FluidStack) ingredient, FluidType.BUCKET_VOLUME))); } }); } } return targets; } @Override public void onComplete() { // NO OP } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/GridRecipeTransferHandler.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSContainerMenus; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage; import com.refinedmods.refinedstorage.network.grid.GridProcessingTransferMessage; import com.refinedmods.refinedstorage.network.grid.GridTransferMessage; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import mezz.jei.api.gui.ingredient.IRecipeSlotView; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.neoforge.NeoForgeTypes; import mezz.jei.api.recipe.RecipeIngredientRole; import mezz.jei.api.recipe.RecipeType; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import mezz.jei.api.recipe.transfer.IRecipeTransferHandler; import net.minecraft.client.gui.screens.Screen; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.RecipeHolder; import net.neoforged.neoforge.fluids.FluidStack; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; public class GridRecipeTransferHandler implements IRecipeTransferHandler { public static final GridRecipeTransferHandler INSTANCE = new GridRecipeTransferHandler(); private static final long TRANSFER_SCROLLBAR_DELAY_MS = 200; private long lastTransferTimeMs; private GridRecipeTransferHandler() { } @Override public Class getContainerClass() { return GridContainerMenu.class; } @Override public Optional> getMenuType() { return Optional.of(RSContainerMenus.GRID.get()); } @Override public RecipeType getRecipeType() { // This is not actually used, as we register with JEI as a universal handler return null; } @Override public @Nullable IRecipeTransferError transferRecipe(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeSlots, Player player, boolean maxTransfer, boolean doTransfer) { if (!(container.getScreenInfoProvider() instanceof GridScreen gridScreen)) { return null; } //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 gridScreen.runActions(); Ingredient.IngredientList ingredientList = new Ingredient.IngredientList(); for (IRecipeSlotView slotView : recipeSlots.getSlotViews(RecipeIngredientRole.INPUT)) { Optional firstStack = slotView.getItemStacks().findAny(); ingredientList.add(new Ingredient(slotView, firstStack.map(ItemStack::getCount).orElse(0))); } IngredientTracker tracker = IngredientTracker.getTracker(container); tracker.updateAvailability(ingredientList, container, player); GridType type = container.getGrid().getGridType(); if (type == GridType.CRAFTING) { return transferRecipeForCraftingGrid(container, recipe, recipeSlots, player, doTransfer, ingredientList); } else if (type == GridType.PATTERN) { return transferRecipeForPatternGrid(container, recipe, recipeSlots, player, doTransfer, ingredientList); } return null; } private RecipeTransferCraftingGridError transferRecipeForCraftingGrid(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeLayout, Player player, boolean doTransfer, Ingredient.IngredientList ingredientList) { if (doTransfer) { if (ingredientList.hasMissingButAutocraftingAvailable() && Screen.hasControlDown()) { ingredientList.createCraftingRequests().forEach((id, count) -> RS.NETWORK_HANDLER.sendToServer( new GridCraftingPreviewRequestMessage( id, count, Screen.hasShiftDown(), false ) )); } else { moveItems(container, recipe, recipeLayout, player); } } else { if (ingredientList.hasMissing()) { return new RecipeTransferCraftingGridError(ingredientList); } } return null; } private IRecipeTransferError transferRecipeForPatternGrid(GridContainerMenu container, Object recipe, IRecipeSlotsView recipeLayout, Player player, boolean doTransfer, Ingredient.IngredientList ingredientList) { if (doTransfer) { moveItems(container, recipe, recipeLayout, player); } else { if (ingredientList.isAutocraftingAvailable()) { return new RecipeTransferPatternGridError(ingredientList); } } return null; } public boolean hasTransferredRecently() { return System.currentTimeMillis() - lastTransferTimeMs <= TRANSFER_SCROLLBAR_DELAY_MS; } private void moveItems(GridContainerMenu gridContainer, Object recipe, IRecipeSlotsView recipeLayout, Player player) { this.lastTransferTimeMs = System.currentTimeMillis(); boolean isCraftingRecipe = false; if (recipe instanceof RecipeHolder castRecipe) { isCraftingRecipe = castRecipe.value().getType() == net.minecraft.world.item.crafting.RecipeType.CRAFTING; } if (gridContainer.getGrid().getGridType() == GridType.PATTERN && !isCraftingRecipe) { moveForProcessing(recipeLayout, gridContainer, player); } else { move(recipeLayout); } } private void move(IRecipeSlotsView recipeSlotsView) { List> inputs = recipeSlotsView.getSlotViews(RecipeIngredientRole.INPUT).stream().map(view -> { //Creating a mutable list List stacks = view.getItemStacks().collect(Collectors.toCollection(ArrayList::new)); //moving the displayed stack to first Optional displayStack = view.getDisplayedItemStack(); displayStack.ifPresent(stack -> { int index = stacks.indexOf(stack); if (index > -1) { stacks.remove(index); stacks.add(0, stack); } }); return stacks; }).toList(); final ItemStack[][] inputsArray = new ItemStack[inputs.size()][]; for (int i = 0; i < inputs.size(); i++) { inputsArray[i] = inputs.get(i).toArray(new ItemStack[0]); } RS.NETWORK_HANDLER.sendToServer(new GridTransferMessage(inputsArray)); } private void moveForProcessing(IRecipeSlotsView recipeLayout, GridContainerMenu gridContainer, Player player) { List inputs = new LinkedList<>(); List outputs = new LinkedList<>(); List fluidInputs = new LinkedList<>(); List fluidOutputs = new LinkedList<>(); List inputSlots = recipeLayout.getSlotViews(RecipeIngredientRole.INPUT); for (IRecipeSlotView view : inputSlots) { handleItemIngredient(inputs, view, gridContainer, player); handleFluidIngredient(fluidInputs, view); } List outputSlots = recipeLayout.getSlotViews(RecipeIngredientRole.OUTPUT); for (IRecipeSlotView view : outputSlots) { handleItemIngredient(outputs, view, gridContainer, player); handleFluidIngredient(fluidOutputs, view); } RS.NETWORK_HANDLER.sendToServer(new GridProcessingTransferMessage(inputs, outputs, fluidInputs, fluidOutputs)); } private void handleFluidIngredient(List list, IRecipeSlotView slotView) { if (slotView != null) { slotView.getDisplayedIngredient(NeoForgeTypes.FLUID_STACK).ifPresent(list::add); } } private void handleItemIngredient(List list, IRecipeSlotView slotView, GridContainerMenu gridContainer, Player player) { if (slotView != null && slotView.getItemStacks().findAny().isPresent()) { ItemStack stack = IngredientTracker.getTracker(gridContainer).findBestMatch(gridContainer, player, slotView.getItemStacks().toList()); if (stack.isEmpty() && slotView.getDisplayedItemStack().isPresent()) { stack = slotView.getDisplayedItemStack().get(); } if (!stack.isEmpty()) { list.add(stack); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/GuiContainerHandler.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.container.BaseContainerMenu; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.widget.sidebutton.SideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import mezz.jei.api.gui.handlers.IGuiContainerHandler; import mezz.jei.api.runtime.IClickableIngredient; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.renderer.Rect2i; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; public class GuiContainerHandler implements IGuiContainerHandler> { private final JeiHelper jeiHelper; public GuiContainerHandler(JeiHelper jeiHelper) { this.jeiHelper = jeiHelper; } @Override public List getGuiExtraAreas(AbstractContainerScreen screen) { if (screen instanceof BaseScreen) { List sideButtons = ((BaseScreen) screen).getSideButtons(); List rectangles = new ArrayList<>(); for (SideButton sideButton : sideButtons) { rectangles.add(new Rect2i(sideButton.getX(), sideButton.getY(), sideButton.getWidth(), sideButton.getHeight())); } return rectangles; } return Collections.emptyList(); } @Override public Optional> getClickableIngredientUnderMouse(AbstractContainerScreen screen, double mouseX, double mouseY) { mouseX -= screen.getGuiLeft(); mouseY -= screen.getGuiTop(); if (screen instanceof GridScreen) { GridScreen grid = (GridScreen) screen; if (!grid.getSearchField().isFocused() && grid.isOverSlotArea(mouseX, mouseY)) { boolean inRange = grid.getSlotNumber() >= 0 && grid.getSlotNumber() < grid.getView().getStacks().size(); Rect2i area = new Rect2i(grid.getSlotNumberX(), grid.getSlotNumberY(), 18, 18); return inRange ? jeiHelper.makeClickableIngredient(grid.getView().getStacks().get(grid.getSlotNumber()).getIngredient(), area) : Optional.empty(); } } if (screen.getMenu() instanceof BaseContainerMenu) { for (FluidFilterSlot slot : ((BaseContainerMenu) screen.getMenu()).getFluidSlots()) { FluidStack fluidInSlot = slot.getFluidInventory().getFluid(slot.getSlotIndex()); if (!fluidInSlot.isEmpty() && RenderUtils.inBounds(slot.x, slot.y, 18, 18, mouseX, mouseY)) { Rect2i area = new Rect2i(slot.x, slot.y, 18, 18); return jeiHelper.makeClickableIngredient(fluidInSlot, area); } } } return Optional.empty(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/HollowCoverCraftingCategoryExtension.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.item.CoverItem; import com.refinedmods.refinedstorage.recipe.HollowCoverRecipe; import mezz.jei.api.gui.builder.IRecipeLayoutBuilder; import mezz.jei.api.gui.builder.IRecipeSlotBuilder; import mezz.jei.api.gui.ingredient.ICraftingGridHelper; import mezz.jei.api.recipe.IFocusGroup; import mezz.jei.api.recipe.category.extensions.vanilla.crafting.ICraftingCategoryExtension; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.crafting.RecipeHolder; import net.minecraft.world.level.block.Block; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; public class HollowCoverCraftingCategoryExtension implements ICraftingCategoryExtension { @Override public void setRecipe(RecipeHolder recipe, IRecipeLayoutBuilder builder, ICraftingGridHelper craftingGridHelper, IFocusGroup focuses) { List> stacks = new ArrayList<>(Collections.nCopies(9, new ArrayList<>())); List input = new ArrayList<>(); List output = new ArrayList<>(); for (Block block : BuiltInRegistries.BLOCK) { Item item = Item.BY_BLOCK.get(block); if (item == null || item == Items.AIR) { continue; } ItemStack itemStack = new ItemStack(item); if (CoverManager.isValidCover(itemStack)) { ItemStack fullCover = new ItemStack(RSItems.COVER.get()); CoverItem.setItem(fullCover, itemStack); input.add(fullCover); ItemStack hollowCover = new ItemStack(RSItems.HOLLOW_COVER.get()); CoverItem.setItem(hollowCover, itemStack); output.add(hollowCover); } } stacks.set(4, input); List inputSlots = craftingGridHelper.createAndSetInputs(builder, stacks, 0, 0); IRecipeSlotBuilder outputSlot = craftingGridHelper.createAndSetOutputs(builder, output); builder.createFocusLink(inputSlots.get(4), outputSlot); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/Ingredient.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import mezz.jei.api.gui.ingredient.IRecipeSlotView; import java.util.*; class Ingredient { private final IRecipeSlotView slotView; private final int required; private UUID craftStackId; private int fulfilled; public Ingredient(IRecipeSlotView view, int count) { this.slotView = view; this.required = count; } public boolean isAvailable() { return getMissingAmount() <= 0; } public int getMissingAmount() { return required - fulfilled; } public boolean isCraftable() { return craftStackId != null; } public IRecipeSlotView getSlotView() { return slotView; } public UUID getCraftStackId() { return craftStackId; } public void setCraftStackId(UUID craftStackId) { this.craftStackId = craftStackId; } public void fulfill(int amount) { fulfilled += amount; } static class IngredientList { List ingredients = new ArrayList<>(); void add(Ingredient ingredient) { ingredients.add(ingredient); } public boolean hasMissing() { return ingredients.stream().anyMatch(ingredient -> !ingredient.isAvailable()); } public boolean hasMissingButAutocraftingAvailable() { return ingredients.stream().anyMatch(ingredient -> !ingredient.isAvailable() && ingredient.isCraftable()); } public boolean isAutocraftingAvailable() { return ingredients.stream().anyMatch(Ingredient::isCraftable); } public Map createCraftingRequests() { Map toRequest = new HashMap<>(); for (Ingredient ingredient : ingredients) { if (!ingredient.isAvailable() && ingredient.isCraftable()) { toRequest.merge(ingredient.getCraftStackId(), ingredient.getMissingAmount(), Integer::sum); } } return toRequest; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/IngredientTracker.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.screen.grid.view.IGridView; import com.refinedmods.refinedstorage.util.ItemStackKey; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import java.util.*; public class IngredientTracker { private static IngredientTracker INSTANCE; private final Map storedItems = new HashMap<>(); private final Map patternItems = new HashMap<>(); private final Map craftableItems = new HashMap<>(); public static IngredientTracker getTracker(GridContainerMenu gridContainer) { if (INSTANCE == null) { INSTANCE = new IngredientTracker(gridContainer); } return INSTANCE; } public static void invalidate() { INSTANCE = null; } public IngredientTracker(GridContainerMenu gridContainer) { // Using IGridView#getStacks will return a *filtered* list of items in the view, // which will cause problems - especially if the user uses JEI synchronised searching. // Instead, we will use IGridView#getAllStacks which provides an unordered view of all GridStacks. IGridView view = ((GridScreen) gridContainer.getScreenInfoProvider()).getView(); //Existing stacks are synced by the fact that they are both referencing the same object. However, new stacks need to be added. view.addDeltaListener((iGridStack -> { if (iGridStack instanceof ItemGridStack stack) { if (stack.isCraftable()) { craftableItems.put(new ItemStackKey(stack.getStack()), stack.getId()); } else { addStack(stack.getStack()); } } })); Collection gridStacks = view.getAllStacks(); // Check grid if (gridContainer.getGrid().isGridActive()) { for (IGridStack gridStack : gridStacks) { if (gridStack instanceof ItemGridStack stackInGrid) { // for craftables we should easily be able to take the hit from hashing the nbt if (stackInGrid.isCraftable()) { craftableItems.put(new ItemStackKey(stackInGrid.getStack()), gridStack.getId()); } else { // for non-craftables we don't hash nbt to avoid the performance hit addStack(stackInGrid.getStack()); } } } } } public void addStack(ItemStack stack) { if (stack.isEmpty()) { return; } if (stack.getItem() instanceof ICraftingPatternProvider) { ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack); if (pattern.isValid()) { for (ItemStack outputStack : pattern.getOutputs()) { patternItems.merge(new ItemStackKey(outputStack), 1, Integer::sum); } } } else { storedItems.merge(new ItemStackKey(stack), stack.getCount(), Integer::sum); } } public ItemStack findBestMatch(GridContainerMenu gridContainer, Player player, List list) { ItemStack resultStack = ItemStack.EMPTY; int count = 0; for (ItemStack listStack : list) { //check crafting matrix if (gridContainer.getGrid().getGridType().equals(GridType.CRAFTING)) { CraftingContainer craftingMatrix = gridContainer.getGrid().getCraftingMatrix(); if (craftingMatrix != null) { for (int matrixSlot = 0; matrixSlot < craftingMatrix.getContainerSize(); matrixSlot++) { ItemStack stackInSlot = craftingMatrix.getItem(matrixSlot); if (API.instance().getComparer().isEqual(listStack, stackInSlot, IComparer.COMPARE_NBT)) { if (stackInSlot.getCount() > count) { count = stackInSlot.getCount(); resultStack = stackInSlot; } } } } } //check inventory for (int inventorySlot = 0; inventorySlot < player.getInventory().getContainerSize(); inventorySlot++) { ItemStack stackInSlot = player.getInventory().getItem(inventorySlot); if (API.instance().getComparer().isEqual(listStack, stackInSlot, IComparer.COMPARE_NBT)) { if (stackInSlot.getCount() > count) { count = stackInSlot.getCount(); resultStack = stackInSlot; } } } //check storage var stored = storedItems.get(new ItemStackKey(listStack)); if (stored != null) { if (stored > count) { resultStack = listStack; count = stored; } } } //If the item is not in storage check patterns autocrafting if (count == 0) { for (ItemStack itemStack : list) { ItemStackKey key = new ItemStackKey(itemStack); if (craftableItems.get(key) != null) { resultStack = itemStack; break; } else if (patternItems.get(key) != null) { resultStack = itemStack; break; } } } return resultStack; } public void updateAvailability(Ingredient.IngredientList ingredientList, GridContainerMenu gridContainer, Player player) { Map usedMatrixStacks = new HashMap<>(); Map usedInventoryStacks = new HashMap<>(); Map usedStoredStacks = new HashMap<>(); //Gather available Stacks for (Ingredient ingredient : ingredientList.ingredients) { ingredient.getSlotView().getItemStacks().takeWhile(stack -> !ingredient.isAvailable()).forEach(stack -> { if(ingredient.getCraftStackId() == null) { ingredient.setCraftStackId(craftableItems.get(new ItemStackKey(stack))); } // Check grid crafting slots if (gridContainer.getGrid().getGridType().equals(GridType.CRAFTING)) { CraftingContainer craftingMatrix = gridContainer.getGrid().getCraftingMatrix(); if (craftingMatrix != null) { for (int matrixSlot = 0; matrixSlot < craftingMatrix.getContainerSize(); matrixSlot++) { if (checkStack(usedMatrixStacks, ingredient, stack, matrixSlot, craftingMatrix.getItem(matrixSlot))) { return; } } } } //read inventory for (int inventorySlot = 0; inventorySlot < player.getInventory().getContainerSize(); inventorySlot++) { if (checkStack(usedInventoryStacks, ingredient, stack, inventorySlot, player.getInventory().getItem(inventorySlot))) { return; } } //Check Stored Stacks ItemStackKey key = new ItemStackKey(stack); Integer stored = storedItems.get(key); if (stored != null) { Integer used = usedStoredStacks.get(key); int amount = Math.min(ingredient.getMissingAmount(), used == null ? stored : stored - used); if (amount > 0) { ingredient.fulfill(amount); usedStoredStacks.put(key, used == null ? amount : used + amount); } } }); } } private boolean checkStack(Map usedMatrixStacks, Ingredient ingredient, ItemStack stack, int slot, ItemStack stackInSlot) { if (API.instance().getComparer().isEqual(stack, stackInSlot, IComparer.COMPARE_NBT)) { Integer used = usedMatrixStacks.get(slot); int amount = Math.min(ingredient.getMissingAmount(), used == null ? stackInSlot.getCount() : stackInSlot.getCount() - used); if (amount > 0) { ingredient.fulfill(amount); usedMatrixStacks.put(slot, used == null ? amount : used + amount); } return ingredient.isAvailable(); } return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/JeiHelper.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import mezz.jei.api.ingredients.ITypedIngredient; import mezz.jei.api.runtime.IClickableIngredient; import mezz.jei.api.runtime.IIngredientManager; import net.minecraft.client.renderer.Rect2i; import java.util.Optional; public class JeiHelper { private final IIngredientManager ingredientManager; public JeiHelper(IIngredientManager ingredientManager) { this.ingredientManager = ingredientManager; } public Optional> makeClickableIngredient(Object ingredient, Rect2i area) { return ingredientManager.createTypedIngredient(ingredient).map(ti -> new ClickableIngredient<>(ti, area)); } private record ClickableIngredient(ITypedIngredient ingredient, Rect2i area) implements IClickableIngredient { @Override public ITypedIngredient getTypedIngredient() { return ingredient; } @Override public Rect2i getArea() { return area; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/JeiIntegration.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import net.neoforged.fml.ModList; public final class JeiIntegration { private JeiIntegration() { } public static boolean isLoaded() { return ModList.get().isLoaded("jei"); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/RSJeiPlugin.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.recipe.CoverRecipe; import com.refinedmods.refinedstorage.recipe.HollowCoverRecipe; import com.refinedmods.refinedstorage.screen.BaseScreen; import mezz.jei.api.IModPlugin; import mezz.jei.api.JeiPlugin; import mezz.jei.api.registration.IGuiHandlerRegistration; import mezz.jei.api.registration.IRecipeTransferRegistration; import mezz.jei.api.registration.ISubtypeRegistration; import mezz.jei.api.registration.IVanillaCategoryExtensionRegistration; import mezz.jei.api.runtime.IJeiRuntime; import net.minecraft.resources.ResourceLocation; @JeiPlugin public class RSJeiPlugin implements IModPlugin { private static final ResourceLocation ID = new ResourceLocation(RS.ID, "plugin"); private static IJeiRuntime runtime; public static IJeiRuntime getRuntime() { return runtime; } @Override public ResourceLocation getPluginUid() { return ID; } @Override public void registerRecipeTransferHandlers(IRecipeTransferRegistration registration) { registration.addUniversalRecipeTransferHandler(GridRecipeTransferHandler.INSTANCE); } @Override public void registerGuiHandlers(IGuiHandlerRegistration registration) { JeiHelper jeiHelper = new JeiHelper(registration.getJeiHelpers().getIngredientManager()); registration.addGenericGuiContainerHandler(BaseScreen.class, new GuiContainerHandler(jeiHelper)); registration.addGhostIngredientHandler(BaseScreen.class, new GhostIngredientHandler()); } @Override public void onRuntimeAvailable(IJeiRuntime runtime) { RSJeiPlugin.runtime = runtime; } @Override public void registerItemSubtypes(ISubtypeRegistration registration) { registration.useNbtForSubtypes(RSItems.COVER.get(), RSItems.HOLLOW_COVER.get()); } @Override public void registerVanillaCategoryExtensions(IVanillaCategoryExtensionRegistration registration) { registration.getCraftingCategory().addExtension(CoverRecipe.class, new CoverCraftingCategoryExtension()); registration.getCraftingCategory().addExtension(HollowCoverRecipe.class, new HollowCoverCraftingCategoryExtension()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/RecipeTransferCraftingGridError.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import mezz.jei.api.gui.ingredient.IRecipeSlotsView; import mezz.jei.api.recipe.transfer.IRecipeTransferError; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import java.awt.*; import java.util.ArrayList; import java.util.List; public class RecipeTransferCraftingGridError implements IRecipeTransferError { protected static final Color AUTOCRAFTING_HIGHLIGHT_COLOR = new Color(0.0f, 0.0f, 1.0f, 0.4f); private static final Color MISSING_HIGHLIGHT_COLOR = new Color(1.0f, 0.0f, 0.0f, 0.4f); private static final boolean HOST_OS_IS_MACOS = System.getProperty("os.name").equals("Mac OS X"); protected final Ingredient.IngredientList ingredientList; public RecipeTransferCraftingGridError(Ingredient.IngredientList ingredientList) { this.ingredientList = ingredientList; } @Override public Type getType() { return Type.COSMETIC; } @Override public int getButtonHighlightColor() { if (ingredientList.hasMissingButAutocraftingAvailable()) { return AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB(); } else if (ingredientList.hasMissing()) { return MISSING_HIGHLIGHT_COLOR.getRGB(); } return IRecipeTransferError.super.getButtonHighlightColor(); } @Override public void showError(GuiGraphics graphics, int mouseX, int mouseY, IRecipeSlotsView recipeSlotsView, int recipeX, int recipeY) { graphics.pose().translate(recipeX, recipeY, 0); List message = drawIngredientHighlights(graphics, recipeX, recipeY); graphics.renderComponentTooltip(Minecraft.getInstance().font, message, mouseX, mouseY); } protected List drawIngredientHighlights(GuiGraphics graphics, int recipeX, int recipeY) { List message = new ArrayList<>(); message.add(Component.translatable("jei.tooltip.transfer")); boolean craftMessage = false; boolean missingMessage = false; for (Ingredient ingredient : ingredientList.ingredients) { if (!ingredient.isAvailable()) { if (ingredient.isCraftable()) { ingredient.getSlotView().drawHighlight(graphics, AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB()); craftMessage = true; } else { ingredient.getSlotView().drawHighlight(graphics, MISSING_HIGHLIGHT_COLOR.getRGB()); missingMessage = true; } } } if (missingMessage) { message.add(Component.translatable("jei.tooltip.error.recipe.transfer.missing").withStyle(ChatFormatting.RED)); } if (craftMessage) { if (HOST_OS_IS_MACOS) { message.add(Component.translatable("gui.refinedstorage.jei.transfer.request_autocrafting_mac").withStyle(ChatFormatting.BLUE)); } else { message.add(Component.translatable("gui.refinedstorage.jei.transfer.request_autocrafting").withStyle(ChatFormatting.BLUE)); } } return message; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/integration/jei/RecipeTransferPatternGridError.java ================================================ package com.refinedmods.refinedstorage.integration.jei; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import java.util.ArrayList; import java.util.List; public class RecipeTransferPatternGridError extends RecipeTransferCraftingGridError { public RecipeTransferPatternGridError(Ingredient.IngredientList ingredients) { super(ingredients); } @Override protected List drawIngredientHighlights(GuiGraphics graphics, int recipeX, int recipeY) { List message = new ArrayList<>(); message.add(Component.translatable("jei.tooltip.transfer")); boolean craftMessage = false; for (Ingredient ingredient : ingredientList.ingredients) { if (ingredient.isCraftable()) { ingredient.getSlotView().drawHighlight(graphics, AUTOCRAFTING_HIGHLIGHT_COLOR.getRGB()); craftMessage = true; } } if (craftMessage) { message.add(Component.translatable("gui.refinedstorage.jei.transfer.autocrafting_available").withStyle(ChatFormatting.BLUE)); } return message; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ConfiguredFluidsInFilterItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.fluid; import com.refinedmods.refinedstorage.item.FilterItem; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class ConfiguredFluidsInFilterItemHandler extends FluidInventory { public ConfiguredFluidsInFilterItemHandler(ItemStack stack) { super(27, Integer.MAX_VALUE); this.addListener((handler, slot, reading) -> { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().put(FilterItem.NBT_FLUID_FILTERS, writeToNbt()); }); if (stack.hasTag() && stack.getTag().contains(FilterItem.NBT_FLUID_FILTERS)) { readFromNbt(stack.getTag().getCompound(FilterItem.NBT_FLUID_FILTERS)); } } public NonNullList getConfiguredFluids() { NonNullList list = NonNullList.create(); for (FluidStack fluid : this.getFluids()) { if (fluid != null) { list.add(fluid); } } return list; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ConfiguredIconInFluidFilterItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.fluid; import com.refinedmods.refinedstorage.item.FilterItem; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class ConfiguredIconInFluidFilterItemHandler extends FluidInventory { public ConfiguredIconInFluidFilterItemHandler(ItemStack stack) { super(1, Integer.MAX_VALUE); this.addListener((handler, slot, reading) -> { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } FilterItem.setFluidIcon(stack, getFluid(slot)); }); FluidStack icon = FilterItem.getFluidIcon(stack); if (!icon.isEmpty()) { setFluid(0, icon); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/fluid/FluidInventory.java ================================================ package com.refinedmods.refinedstorage.inventory.fluid; import com.refinedmods.refinedstorage.inventory.listener.InventoryListener; import net.minecraft.nbt.CompoundTag; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; public class FluidInventory { private static final String NBT_SLOT = "Slot_%d"; private final List> listeners = new ArrayList<>(); private final FluidStack[] fluids; private final int maxAmount; private boolean empty = true; public FluidInventory(int size, int maxAmount) { this.fluids = new FluidStack[size]; for (int i = 0; i < size; ++i) { fluids[i] = FluidStack.EMPTY; } this.maxAmount = maxAmount; } public FluidInventory(int size) { this(size, Integer.MAX_VALUE); } public FluidInventory addListener(InventoryListener listener) { listeners.add(listener); return this; } public int getSlots() { return fluids.length; } public int getMaxAmount() { return maxAmount; } public FluidStack[] getFluids() { return fluids; } @Nonnull public FluidStack getFluid(int slot) { return fluids[slot]; } public void setFluid(int slot, @Nonnull FluidStack stack) { if (stack.getAmount() > maxAmount) { throw new IllegalArgumentException("Fluid size is invalid (given: " + stack.getAmount() + ", max size: " + maxAmount + ")"); } fluids[slot] = stack; onChanged(slot); } public void onChanged(int slot) { listeners.forEach(l -> l.onChanged(this, slot, false)); updateEmptyState(); } public CompoundTag writeToNbt() { CompoundTag tag = new CompoundTag(); for (int i = 0; i < getSlots(); ++i) { FluidStack stack = getFluid(i); if (!stack.isEmpty()) { tag.put(String.format(NBT_SLOT, i), stack.writeToNBT(new CompoundTag())); } } return tag; } public void readFromNbt(CompoundTag tag) { for (int i = 0; i < getSlots(); ++i) { String key = String.format(NBT_SLOT, i); if (tag.contains(key)) { fluids[i] = FluidStack.loadFluidStackFromNBT(tag.getCompound(key)); } } updateEmptyState(); } private void updateEmptyState() { this.empty = true; for (FluidStack fluid : fluids) { if (!fluid.isEmpty()) { this.empty = false; return; } } } public boolean isEmpty() { return empty; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/fluid/ProxyFluidHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.fluid; import javax.annotation.Nonnull; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.templates.FluidTank; public class ProxyFluidHandler implements IFluidHandler { private final FluidTank insertHandler; private final FluidTank extractHandler; public ProxyFluidHandler(FluidTank insertHandler, FluidTank extractHandler) { this.insertHandler = insertHandler; this.extractHandler = extractHandler; } @Override public int getTanks() { return 2; } @Nonnull @Override public FluidStack getFluidInTank(int tank) { return tank == 0 ? insertHandler.getFluidInTank(0) : extractHandler.getFluidInTank(0); } @Override public int getTankCapacity(int tank) { return tank == 0 ? insertHandler.getTankCapacity(0) : extractHandler.getTankCapacity(0); } @Override public boolean isFluidValid(int tank, @Nonnull FluidStack stack) { return tank == 0 ? insertHandler.isFluidValid(0, stack) : extractHandler.isFluidValid(0, stack); } @Override public int fill(FluidStack resource, FluidAction action) { return insertHandler.fill(resource, action); } @Nonnull @Override public FluidStack drain(FluidStack resource, FluidAction action) { return extractHandler.drain(resource, action); } @Nonnull @Override public FluidStack drain(int maxDrain, FluidAction action) { return extractHandler.drain(maxDrain, action); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/BaseItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import com.refinedmods.refinedstorage.inventory.listener.InventoryListener; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemStackHandler; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; public class BaseItemHandler extends ItemStackHandler { private final List> listeners = new ArrayList<>(); private final List> validators = new ArrayList<>(); private boolean empty = true; private boolean reading; public BaseItemHandler(int size) { super(size); } public BaseItemHandler addValidator(Predicate validator) { validators.add(validator); return this; } public BaseItemHandler addListener(InventoryListener listener) { listeners.add(listener); return this; } @Override @Nonnull public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { if (!validators.isEmpty()) { for (Predicate validator : validators) { if (validator.test(stack)) { return super.insertItem(slot, stack, simulate); } } return stack; } return super.insertItem(slot, stack, simulate); } @Override protected void onContentsChanged(int slot) { super.onContentsChanged(slot); onChanged(slot); } public void onChanged(int slot) { this.empty = stacks.stream().allMatch(ItemStack::isEmpty); this.listeners.forEach(l -> l.onChanged(this, slot, reading)); } @Override public void deserializeNBT(CompoundTag tag) { super.deserializeNBT(tag); this.empty = stacks.stream().allMatch(ItemStack::isEmpty); } public boolean isEmpty() { return empty; } public void setReading(boolean reading) { this.reading = reading; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/ConfiguredIconInFilterItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import com.refinedmods.refinedstorage.item.FilterItem; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemStackHandler; public class ConfiguredIconInFilterItemHandler extends ItemStackHandler { private final ItemStack filterItem; public ConfiguredIconInFilterItemHandler(ItemStack filterItem) { super(1); this.filterItem = filterItem; setStackInSlot(0, FilterItem.getIcon(filterItem)); } @Override protected void onContentsChanged(int slot) { super.onContentsChanged(slot); FilterItem.setIcon(filterItem, getStackInSlot(0)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/ConfiguredItemsInFilterItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.core.NonNullList; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemStackHandler; public class ConfiguredItemsInFilterItemHandler extends ItemStackHandler { private final ItemStack stack; public ConfiguredItemsInFilterItemHandler(ItemStack stack) { super(27); this.stack = stack; if (stack.hasTag()) { StackUtils.readItems(this, 0, stack.getTag()); } } @Override protected void onContentsChanged(int slot) { super.onContentsChanged(slot); if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } StackUtils.writeItems(this, 0, stack.getTag()); } public NonNullList getConfiguredItems() { return stacks; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/FilterItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.apiimpl.network.grid.GridTab; import com.refinedmods.refinedstorage.apiimpl.util.FluidFilter; import com.refinedmods.refinedstorage.apiimpl.util.ItemFilter; import com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.validator.ItemValidator; import com.refinedmods.refinedstorage.item.FilterItem; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import net.minecraft.world.item.ItemStack; import net.neoforged.fml.LogicalSide; import net.neoforged.fml.util.thread.EffectiveSide; import net.neoforged.neoforge.fluids.FluidStack; import java.util.ArrayList; import java.util.List; public class FilterItemHandler extends BaseItemHandler { private final List filters; private final List tabs; public FilterItemHandler(List filters, List tabs) { super(4); this.filters = filters; this.tabs = tabs; this.addValidator(new ItemValidator(RSItems.FILTER.get())); } @Override protected void onContentsChanged(int slot) { super.onContentsChanged(slot); filters.clear(); tabs.clear(); for (int i = 0; i < getSlots(); ++i) { ItemStack filterItem = getStackInSlot(i); if (!filterItem.isEmpty()) { handleFilterItem(filterItem); } } if (EffectiveSide.get() == LogicalSide.CLIENT) { BaseScreen.executeLater(GridScreen.class, grid -> grid.getView().sort()); } } private void handleFilterItem(ItemStack filterItem) { ItemStack icon = FilterItem.getIcon(filterItem); FluidStack fluidIcon = FilterItem.getFluidIcon(filterItem); int compare = FilterItem.getCompare(filterItem); int mode = FilterItem.getMode(filterItem); boolean modFilter = FilterItem.isModFilter(filterItem); List foundFilters = new ArrayList<>(); for (ItemStack stack : new ConfiguredItemsInFilterItemHandler(filterItem).getConfiguredItems()) { if (stack.getItem() == RSItems.FILTER.get()) { handleFilterItem(stack); } else if (!stack.isEmpty()) { foundFilters.add(new ItemFilter(stack, compare, mode, modFilter)); } } for (FluidStack stack : new ConfiguredFluidsInFilterItemHandler(filterItem).getConfiguredFluids()) { foundFilters.add(new FluidFilter(stack, compare, mode, modFilter)); } if (icon.isEmpty() && fluidIcon.isEmpty()) { filters.addAll(foundFilters); } else { tabs.add(new GridTab(foundFilters, FilterItem.getFilterName(filterItem), icon, fluidIcon)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/ProxyItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.IItemHandler; import javax.annotation.Nonnull; public class ProxyItemHandler implements IItemHandler { private final IItemHandler insertHandler; private final IItemHandler extractHandler; public ProxyItemHandler(IItemHandler insertHandler, IItemHandler extractHandler) { this.insertHandler = insertHandler; this.extractHandler = extractHandler; } @Override public int getSlots() { return insertHandler.getSlots() + extractHandler.getSlots(); } @Nonnull @Override public ItemStack getStackInSlot(int slot) { return slot < insertHandler.getSlots() ? insertHandler.getStackInSlot(slot) : extractHandler.getStackInSlot(slot - insertHandler.getSlots()); } @Nonnull @Override public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { return slot < insertHandler.getSlots() ? insertHandler.insertItem(slot, stack, simulate) : stack; } @Nonnull @Override public ItemStack extractItem(int slot, int amount, boolean simulate) { return slot >= insertHandler.getSlots() ? extractHandler.extractItem(slot - insertHandler.getSlots(), amount, simulate) : ItemStack.EMPTY; } @Override public int getSlotLimit(int slot) { return slot < insertHandler.getSlots() ? insertHandler.getSlotLimit(slot) : extractHandler.getSlotLimit(slot - insertHandler.getSlots()); } @Override public boolean isItemValid(int slot, @Nonnull ItemStack stack) { return slot < insertHandler.getSlots() ? insertHandler.isItemValid(slot, stack) : extractHandler.isItemValid(slot - extractHandler.getSlots(), stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/UpgradeItemHandler.java ================================================ package com.refinedmods.refinedstorage.inventory.item; import com.refinedmods.refinedstorage.inventory.item.validator.UpgradeItemValidator; import com.refinedmods.refinedstorage.item.UpgradeItem; import net.minecraft.world.item.ItemStack; public class UpgradeItemHandler extends BaseItemHandler { public UpgradeItemHandler(int size, UpgradeItem.Type... supportedUpgrades) { super(size); for (UpgradeItem.Type supportedUpgrade : supportedUpgrades) { addValidator(new UpgradeItemValidator(supportedUpgrade)); } } public int getSpeed() { return getSpeed(9, 2); } public int getSpeed(int speed, int speedIncrease) { for (int i = 0; i < getSlots(); ++i) { ItemStack slot = getStackInSlot(i); if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == UpgradeItem.Type.SPEED) { speed -= speedIncrease; } } return speed; } public boolean hasUpgrade(UpgradeItem.Type type) { for (int i = 0; i < getSlots(); ++i) { ItemStack slot = getStackInSlot(i); if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == type) { return true; } } return false; } public int getUpgradeCount(UpgradeItem.Type type) { int upgrades = 0; for (int i = 0; i < getSlots(); ++i) { ItemStack slot = getStackInSlot(i); if (slot.getItem() instanceof UpgradeItem && ((UpgradeItem) slot.getItem()).getType() == type) { upgrades++; } } return upgrades; } public int getEnergyUsage() { int usage = 0; for (int i = 0; i < getSlots(); ++i) { ItemStack slot = getStackInSlot(i); if (slot.getItem() instanceof UpgradeItem) { usage += ((UpgradeItem) slot.getItem()).getType().getEnergyUsage(); } } return usage; } public int getStackInteractCount() { return hasUpgrade(UpgradeItem.Type.STACK) ? 64 : 1; } @Override public int getSlotLimit(int slot) { return 1; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/ItemValidator.java ================================================ package com.refinedmods.refinedstorage.inventory.item.validator; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import java.util.function.Predicate; public class ItemValidator implements Predicate { private final Item item; public ItemValidator(Item item) { this.item = item; } @Override public boolean test(ItemStack stack) { return stack.getItem() == item; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/PatternItemValidator.java ================================================ package com.refinedmods.refinedstorage.inventory.item.validator; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.item.PatternItem; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import java.util.function.Predicate; public class PatternItemValidator implements Predicate { private final Level level; public PatternItemValidator(Level level) { this.level = level; } @Override public boolean test(ItemStack stack) { if (stack.getItem() == RSItems.PATTERN.get()) { return PatternItem.fromCache(level, stack).isValid(); } return stack.getItem() instanceof ICraftingPatternProvider && ((ICraftingPatternProvider) stack.getItem()).create(level, stack, null).isValid(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/StorageDiskItemValidator.java ================================================ package com.refinedmods.refinedstorage.inventory.item.validator; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import net.minecraft.world.item.ItemStack; import java.util.function.Predicate; public class StorageDiskItemValidator implements Predicate { @Override public boolean test(ItemStack stack) { return stack.getItem() instanceof IStorageDiskProvider && ((IStorageDiskProvider) stack.getItem()).isValid(stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/item/validator/UpgradeItemValidator.java ================================================ package com.refinedmods.refinedstorage.inventory.item.validator; import com.refinedmods.refinedstorage.item.UpgradeItem; import net.minecraft.world.item.ItemStack; import java.util.function.Predicate; public class UpgradeItemValidator implements Predicate { private final UpgradeItem.Type type; public UpgradeItemValidator(UpgradeItem.Type type) { this.type = type; } @Override public boolean test(ItemStack stack) { return stack.getItem() instanceof UpgradeItem && ((UpgradeItem) stack.getItem()).getType() == type; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/listener/BlockEntityInventoryListener.java ================================================ package com.refinedmods.refinedstorage.inventory.listener; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import net.minecraft.world.level.block.entity.BlockEntity; public class BlockEntityInventoryListener implements InventoryListener { private final BlockEntity blockEntity; public BlockEntityInventoryListener(BlockEntity blockEntity) { this.blockEntity = blockEntity; } @Override public void onChanged(BaseItemHandler handler, int slot, boolean reading) { if (!reading) { blockEntity.setChanged(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/listener/InventoryListener.java ================================================ package com.refinedmods.refinedstorage.inventory.listener; public interface InventoryListener { void onChanged(T handler, int slot, boolean reading); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/listener/NetworkNodeFluidInventoryListener.java ================================================ package com.refinedmods.refinedstorage.inventory.listener; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; public class NetworkNodeFluidInventoryListener implements InventoryListener { private final INetworkNode node; public NetworkNodeFluidInventoryListener(INetworkNode node) { this.node = node; } @Override public void onChanged(FluidInventory handler, int slot, boolean reading) { if (!reading) { node.markDirty(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/listener/NetworkNodeInventoryListener.java ================================================ package com.refinedmods.refinedstorage.inventory.listener; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; public class NetworkNodeInventoryListener implements InventoryListener { private final INetworkNode node; public NetworkNodeInventoryListener(INetworkNode node) { this.node = node; } @Override public void onChanged(BaseItemHandler handler, int slot, boolean reading) { if (!reading) { node.markDirty(); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/inventory/player/PlayerSlot.java ================================================ package com.refinedmods.refinedstorage.inventory.player; import com.refinedmods.refinedstorage.integration.curios.CuriosIntegration; import com.refinedmods.refinedstorage.util.PacketBufferUtils; import java.util.Optional; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import top.theillusivec4.curios.api.CuriosApi; import top.theillusivec4.curios.api.type.capability.ICuriosItemHandler; import top.theillusivec4.curios.api.type.inventory.ICurioStacksHandler; public class PlayerSlot { int slot; String curioSlot; public PlayerSlot(int slot, String curioSlot) { this.slot = slot; this.curioSlot = curioSlot; } public PlayerSlot(int slot) { this.slot = slot; } public PlayerSlot(FriendlyByteBuf buffer) { slot = buffer.readInt(); if (buffer.readBoolean()) { curioSlot = PacketBufferUtils.readString(buffer); } } public static PlayerSlot getSlotForHand(Player player, InteractionHand hand) { if (hand == InteractionHand.MAIN_HAND) { return new PlayerSlot(player.getInventory().selected); } return new PlayerSlot(Inventory.SLOT_OFFHAND); } public ItemStack getStackFromSlot(Player player) { if (curioSlot == null || !CuriosIntegration.isLoaded()) { return player.getInventory().getItem(slot); } Optional curiosInventory = CuriosApi.getCuriosInventory(player); Optional stacksHandler = curiosInventory.flatMap((handler -> handler.getStacksHandler(curioSlot) )); Optional stack = stacksHandler.map(handler -> handler.getStacks().getStackInSlot(slot)); return stack.orElse(ItemStack.EMPTY); } public void writePlayerSlot(FriendlyByteBuf buffer) { buffer.writeInt(slot); buffer.writeBoolean(curioSlot != null); if (curioSlot != null) { buffer.writeUtf(curioSlot); } } public int getSlotIdInPlayerInventory() { if (curioSlot != null) { return -1; } return slot; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/CoreItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class CoreItem extends Item { public CoreItem() { super(new Item.Properties()); } public enum Type { CONSTRUCTION, DESTRUCTION } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/CoverItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import com.refinedmods.refinedstorage.block.CableBlock; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; public class CoverItem extends Item { private static final String NBT_ITEM = "Item"; public CoverItem() { super(new Item.Properties()); } public static void setItem(ItemStack cover, ItemStack item) { if (!cover.hasTag()) { cover.setTag(new CompoundTag()); } ItemStack result = item.copy(); result.setCount(1); cover.getTag().put(NBT_ITEM, result.save(new CompoundTag())); } @Nonnull public static ItemStack getItem(ItemStack cover) { if (!cover.hasTag() || !cover.getTag().contains(NBT_ITEM)) { return ItemStack.EMPTY; } return ItemStack.of(cover.getTag().getCompound(NBT_ITEM)); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); ItemStack item = getItem(stack); if (!item.isEmpty()) { tooltip.add(item.getItem().getName(item).copy().withStyle(ChatFormatting.GRAY)); } } @Override public InteractionResult useOn(UseOnContext context) { BlockPos pos = context.getClickedPos(); Direction facing = context.getClickedFace(); Level level = context.getLevel(); ItemStack stack = context.getPlayer().getItemInHand(context.getHand()); BlockEntity blockEntity = level.getBlockEntity(pos); // Support placing on the bottom side without too much hassle. if (!canPlaceOn(level, pos, facing)) { pos = pos.above(); facing = Direction.DOWN; blockEntity = level.getBlockEntity(pos); } if (canPlaceOn(level, pos, facing)) { if (level.isClientSide) { level.getModelDataManager().requestRefresh(blockEntity); return InteractionResult.SUCCESS; } INetworkNode node = ((NetworkNodeBlockEntity) blockEntity).getNode(); if (node.getNetwork() != null && !node.getNetwork().getSecurityManager().hasPermission(Permission.BUILD, context.getPlayer())) { LevelUtils.sendNoPermissionMessage(context.getPlayer()); return InteractionResult.FAIL; } if (((ICoverable) node).getCoverManager().setCover(facing, createCover(getItem(stack)))) { context.getPlayer().getItemInHand(context.getHand()).shrink(1); LevelUtils.updateBlock(level, pos); API.instance().getNetworkNodeManager((ServerLevel) level).markForSaving(); return InteractionResult.SUCCESS; } return InteractionResult.FAIL; } return InteractionResult.PASS; } private boolean canPlaceOn(Level level, BlockPos pos, Direction facing) { return level.getBlockEntity(pos) instanceof NetworkNodeBlockEntity && ((NetworkNodeBlockEntity) level.getBlockEntity(pos)).getNode() instanceof ICoverable && !CableBlock.hasVisualConnectionOnSide(level.getBlockState(pos), facing); } protected Cover createCover(ItemStack stack) { return new Cover(stack, CoverType.NORMAL); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/EnergyItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.energy.ItemEnergyStorage; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import javax.annotation.Nullable; import java.util.List; import java.util.function.Supplier; public abstract class EnergyItem extends Item { private final Supplier energyCapacity; private final boolean creative; protected EnergyItem(Item.Properties properties, boolean creative, Supplier energyCapacity) { super(properties); this.creative = creative; this.energyCapacity = energyCapacity; } public EnergyStorage createEnergyStorage(ItemStack stack) { return new ItemEnergyStorage(stack, energyCapacity.get()); } @Override public boolean isBarVisible(ItemStack stack) { return !creative; } @Override public int getBarWidth(ItemStack stack) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return 0; } float stored = (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored(); return Math.round(stored * 13F); } @Override public int getBarColor(ItemStack stack) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return super.getBarColor(stack); } return Mth.hsvToRgb(Math.max(0.0F, (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored()) / 3.0F, 1.0F, 1.0F); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (!creative) { final IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return; } tooltip.add(Component.translatable("misc.refinedstorage.energy_stored", energy.getEnergyStored(), energy.getMaxEnergyStored()).setStyle(Styles.GRAY)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/FilterItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.container.FilterContainerMenu; import com.refinedmods.refinedstorage.inventory.fluid.ConfiguredFluidsInFilterItemHandler; import com.refinedmods.refinedstorage.inventory.item.ConfiguredItemsInFilterItemHandler; import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; public class FilterItem extends Item { public static final String NBT_FLUID_FILTERS = "FluidFilters"; private static final String NBT_COMPARE = "Compare"; private static final String NBT_MODE = "Mode"; private static final String NBT_MOD_FILTER = "ModFilter"; private static final String NBT_NAME = "Name"; private static final String NBT_ICON = "Icon"; private static final String NBT_FLUID_ICON = "FluidIcon"; private static final String NBT_TYPE = "Type"; public FilterItem() { super(new Item.Properties().stacksTo(1)); } public static int getCompare(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(NBT_COMPARE)) ? stack.getTag().getInt(NBT_COMPARE) : IComparer.COMPARE_NBT; } public static void setCompare(ItemStack stack, int compare) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_COMPARE, compare); } public static int getMode(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(NBT_MODE)) ? stack.getTag().getInt(NBT_MODE) : IFilter.MODE_WHITELIST; } public static void setMode(ItemStack stack, int mode) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_MODE, mode); } public static boolean isModFilter(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_MOD_FILTER) && stack.getTag().getBoolean(NBT_MOD_FILTER); } public static void setModFilter(ItemStack stack, boolean modFilter) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putBoolean(NBT_MOD_FILTER, modFilter); } public static String getFilterName(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_NAME) ? stack.getTag().getString(NBT_NAME) : ""; } public static void setName(ItemStack stack, String name) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putString(NBT_NAME, name); } @Nonnull public static ItemStack getIcon(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_ICON) ? ItemStack.of(stack.getTag().getCompound(NBT_ICON)) : ItemStack.EMPTY; } public static void setIcon(ItemStack stack, ItemStack icon) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().put(NBT_ICON, icon.save(new CompoundTag())); } public static void setFluidIcon(ItemStack stack, @Nullable FluidStack icon) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } if (icon == null) { stack.getTag().remove(NBT_FLUID_ICON); } else { stack.getTag().put(NBT_FLUID_ICON, icon.writeToNBT(new CompoundTag())); } } @Nonnull public static FluidStack getFluidIcon(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_FLUID_ICON) ? FluidStack.loadFluidStackFromNBT(stack.getTag().getCompound(NBT_FLUID_ICON)) : FluidStack.EMPTY; } public static int getType(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_TYPE) ? stack.getTag().getInt(NBT_TYPE) : IType.ITEMS; } public static void setType(ItemStack stack, int type) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_TYPE, type); } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if (!level.isClientSide) { if (player.isCrouching()) { return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.FILTER.get())); } player.openMenu(new MenuProvider() { @Override public Component getDisplayName() { return Component.translatable("gui.refinedstorage.filter"); } @Override public AbstractContainerMenu createMenu(int windowId, Inventory inventory, Player player) { return new FilterContainerMenu(player, inventory.getSelected(), windowId); } }); } return new InteractionResultHolder<>(InteractionResult.CONSUME, stack); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); tooltip.add(Component.translatable("sidebutton.refinedstorage.mode." + (getMode(stack) == IFilter.MODE_WHITELIST ? "whitelist" : "blacklist")).setStyle(Styles.YELLOW)); if (isModFilter(stack)) { tooltip.add(Component.translatable("gui.refinedstorage.filter.mod_filter").setStyle(Styles.BLUE)); } RenderUtils.addCombinedItemsToTooltip(tooltip, false, new ConfiguredItemsInFilterItemHandler(stack).getConfiguredItems()); RenderUtils.addCombinedFluidsToTooltip(tooltip, false, new ConfiguredFluidsInFilterItemHandler(stack).getConfiguredFluids()); } @Override public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/FluidStorageDiskItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class FluidStorageDiskItem extends Item implements IStorageDiskProvider { private static final String NBT_ID = "Id"; private final FluidStorageType type; public FluidStorageDiskItem(FluidStorageType type) { super(new Item.Properties().stacksTo(1)); this.type = type; } @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { super.inventoryTick(stack, level, entity, slot, selected); if (!level.isClientSide && !stack.hasTag() && entity instanceof Player) { UUID id = UUID.randomUUID(); API.instance().getStorageDiskManager((ServerLevel) level).set(id, API.instance().createDefaultFluidDisk((ServerLevel) level, getCapacity(stack), (Player) entity)); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); setId(stack, id); } } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (isValid(stack)) { UUID id = getId(stack); API.instance().getStorageDiskSync().sendRequest(id); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id); if (data != null) { if (data.getCapacity() == -1) { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY)); } else { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored_capacity", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY)); } } if (flag.isAdvanced()) { tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY)); } } } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack diskStack = player.getItemInHand(hand); if (!level.isClientSide && player.isCrouching() && type != FluidStorageType.CREATIVE) { IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(diskStack); if (disk != null && disk.getStored() == 0) { ItemStack storagePart = new ItemStack(FluidStoragePartItem.getByType(type), diskStack.getCount()); if (!player.getInventory().add(storagePart.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart); } API.instance().getStorageDiskManager((ServerLevel) level).remove(getId(diskStack)); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING.get())); } } return new InteractionResultHolder<>(InteractionResult.PASS, diskStack); } @Override public int getEntityLifespan(ItemStack stack, Level level) { return Integer.MAX_VALUE; } @Override public UUID getId(ItemStack disk) { return disk.getTag().getUUID(NBT_ID); } @Override public void setId(ItemStack disk, UUID id) { disk.setTag(new CompoundTag()); disk.getTag().putUUID(NBT_ID, id); } @Override public boolean isValid(ItemStack disk) { return disk.hasTag() && disk.getTag().hasUUID(NBT_ID); } @Override public int getCapacity(ItemStack disk) { return type.getCapacity(); } @Override public StorageType getType() { return StorageType.FLUID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/FluidStoragePartItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import net.minecraft.world.item.Item; public class FluidStoragePartItem extends Item { public FluidStoragePartItem() { super(new Item.Properties()); } public static FluidStoragePartItem getByType(FluidStorageType type) { return RSItems.FLUID_STORAGE_PARTS.get(type).get(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/HollowCoverItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import net.minecraft.world.item.ItemStack; public class HollowCoverItem extends CoverItem { public HollowCoverItem() { super(); } @Override protected Cover createCover(ItemStack stack) { return new Cover(stack, CoverType.HOLLOW); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/NetworkCardItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.block.NetworkReceiverBlock; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import javax.annotation.Nullable; import java.util.List; public class NetworkCardItem extends Item { private static final String NBT_RECEIVER_X = "ReceiverX"; private static final String NBT_RECEIVER_Y = "ReceiverY"; private static final String NBT_RECEIVER_Z = "ReceiverZ"; private static final String NBT_DIMENSION = "Dimension"; public NetworkCardItem() { super(new Item.Properties().stacksTo(1)); } @Nullable public static BlockPos getReceiver(ItemStack stack) { if (stack.hasTag() && stack.getTag().contains(NBT_RECEIVER_X) && stack.getTag().contains(NBT_RECEIVER_Y) && stack.getTag().contains(NBT_RECEIVER_Z)) { return new BlockPos( stack.getTag().getInt(NBT_RECEIVER_X), stack.getTag().getInt(NBT_RECEIVER_Y), stack.getTag().getInt(NBT_RECEIVER_Z) ); } return null; } @Nullable public static ResourceKey getDimension(ItemStack stack) { if (stack.hasTag() && stack.getTag().contains(NBT_DIMENSION)) { ResourceLocation name = ResourceLocation.tryParse(stack.getTag().getString(NBT_DIMENSION)); if (name == null) { return null; } return ResourceKey.create(Registries.DIMENSION, name); } return null; } @Override public InteractionResult useOn(UseOnContext ctx) { Block block = ctx.getLevel().getBlockState(ctx.getClickedPos()).getBlock(); if (block instanceof NetworkReceiverBlock) { CompoundTag tag = new CompoundTag(); tag.putInt(NBT_RECEIVER_X, ctx.getClickedPos().getX()); tag.putInt(NBT_RECEIVER_Y, ctx.getClickedPos().getY()); tag.putInt(NBT_RECEIVER_Z, ctx.getClickedPos().getZ()); tag.putString(NBT_DIMENSION, ctx.getLevel().dimension().location().toString()); ctx.getPlayer().getItemInHand(ctx.getHand()).setTag(tag); return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); BlockPos pos = getReceiver(stack); ResourceKey type = getDimension(stack); if (pos != null && type != null) { tooltip.add(Component.translatable( "misc.refinedstorage.network_card.tooltip", pos.getX(), pos.getY(), pos.getZ(), type.location().toString() ).setStyle(Styles.GRAY)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/NetworkItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.item.INetworkItemProvider; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.util.NetworkUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; public abstract class NetworkItem extends EnergyItem implements INetworkItemProvider { private static final String NBT_NODE_X = "NodeX"; private static final String NBT_NODE_Y = "NodeY"; private static final String NBT_NODE_Z = "NodeZ"; private static final String NBT_DIMENSION = "Dimension"; protected NetworkItem(Item.Properties item, boolean creative, Supplier energyCapacity) { super(item, creative, energyCapacity); } @Nullable public static ResourceKey getDimension(ItemStack stack) { if (stack.hasTag() && stack.getTag().contains(NBT_DIMENSION)) { ResourceLocation name = ResourceLocation.tryParse(stack.getTag().getString(NBT_DIMENSION)); if (name == null) { return null; } return ResourceKey.create(Registries.DIMENSION, name); } return null; } public static int getX(ItemStack stack) { return stack.getTag().getInt(NBT_NODE_X); } public static int getY(ItemStack stack) { return stack.getTag().getInt(NBT_NODE_Y); } public static int getZ(ItemStack stack) { return stack.getTag().getInt(NBT_NODE_Z); } public static boolean isValid(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_NODE_X) && stack.getTag().contains(NBT_NODE_Y) && stack.getTag().contains(NBT_NODE_Z) && stack.getTag().contains(NBT_DIMENSION); } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if (!level.isClientSide) { applyNetwork(level.getServer(), stack, n -> n.getNetworkItemManager().open(player, player.getItemInHand(hand), PlayerSlot.getSlotForHand(player, hand)), player::sendSystemMessage); } return InteractionResultHolder.success(stack); } public void applyNetwork(MinecraftServer server, ItemStack stack, Consumer onNetwork, Consumer onError) { MutableComponent notFound = Component.translatable("misc.refinedstorage.network_item.not_found"); if (!isValid(stack)) { onError.accept(notFound); return; } ResourceKey dimension = getDimension(stack); if (dimension == null) { onError.accept(notFound); return; } Level nodeLevel = server.getLevel(dimension); if (nodeLevel == null) { onError.accept(notFound); return; } BlockPos pos = new BlockPos(getX(stack), getY(stack), getZ(stack)); if (!nodeLevel.isLoaded(pos)) { onError.accept(notFound); return; } INetwork network = NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(nodeLevel.getBlockEntity(pos))); if (network == null) { onError.accept(notFound); return; } onNetwork.accept(network); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (isValid(stack)) { tooltip.add(Component.translatable("misc.refinedstorage.network_item.tooltip", getX(stack), getY(stack), getZ(stack)).setStyle(Styles.GRAY)); } } @Override public InteractionResult interactLivingEntity(ItemStack stack, Player playerIn, LivingEntity target, InteractionHand hand) { return super.interactLivingEntity(stack, playerIn, target, hand); } @Override public InteractionResult useOn(UseOnContext ctx) { ItemStack stack = ctx.getPlayer().getItemInHand(ctx.getHand()); INetwork network = NetworkUtils.getNetworkFromNode(NetworkUtils.getNodeFromBlockEntity(ctx.getLevel().getBlockEntity(ctx.getClickedPos()))); if (network != null) { CompoundTag tag = stack.getTag(); if (tag == null) { tag = new CompoundTag(); } tag.putInt(NBT_NODE_X, network.getPosition().getX()); tag.putInt(NBT_NODE_Y, network.getPosition().getY()); tag.putInt(NBT_NODE_Z, network.getPosition().getZ()); tag.putString(NBT_DIMENSION, ctx.getLevel().dimension().location().toString()); stack.setTag(tag); return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/PatternItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternContainer; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternProvider; import com.refinedmods.refinedstorage.apiimpl.autocrafting.AllowedTagList; import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPattern; import com.refinedmods.refinedstorage.apiimpl.autocrafting.CraftingPatternFactory; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.render.Styles; import com.refinedmods.refinedstorage.render.blockentity.PatternItemBlockEntityRenderer; import com.refinedmods.refinedstorage.util.ItemStackKey; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collectors; public class PatternItem extends Item implements ICraftingPatternProvider { private static final Map CACHE = new HashMap<>(); private static final String NBT_VERSION = "Version"; private static final String NBT_INPUT_SLOT = "Input_%d"; private static final String NBT_OUTPUT_SLOT = "Output_%d"; private static final String NBT_FLUID_INPUT_SLOT = "FluidInput_%d"; private static final String NBT_FLUID_OUTPUT_SLOT = "FluidOutput_%d"; private static final String NBT_EXACT = "Exact"; private static final String NBT_PROCESSING = "Processing"; private static final String NBT_ALLOWED_TAGS = "AllowedTags"; private static final int VERSION = 1; public PatternItem() { super(new Item.Properties()); } public static ICraftingPattern fromCache(Level level, ItemStack stack) { ICraftingPattern pattern = CACHE.computeIfAbsent( new ItemStackKey(stack), s -> CraftingPatternFactory.INSTANCE.create(level, null, s.getStack()) ); // A number that is not too crazy but hopefully is not normally reachable, // just reset the cache to keep its size limited so this is not a memory leak if (CACHE.size() > 16384) { CACHE.clear(); } return pattern; } public static void setInputSlot(ItemStack pattern, int slot, ItemStack stack) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().put(String.format(NBT_INPUT_SLOT, slot), stack.save(new CompoundTag())); } @Nonnull public static ItemStack getInputSlot(ItemStack pattern, int slot) { String id = String.format(NBT_INPUT_SLOT, slot); if (!pattern.hasTag() || !pattern.getTag().contains(id)) { return ItemStack.EMPTY; } return ItemStack.of(pattern.getTag().getCompound(id)); } public static void setOutputSlot(ItemStack pattern, int slot, ItemStack stack) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().put(String.format(NBT_OUTPUT_SLOT, slot), stack.save(new CompoundTag())); } @Nonnull public static ItemStack getOutputSlot(ItemStack pattern, int slot) { String id = String.format(NBT_OUTPUT_SLOT, slot); if (!pattern.hasTag() || !pattern.getTag().contains(id)) { return ItemStack.EMPTY; } return ItemStack.of(pattern.getTag().getCompound(id)); } public static void setFluidInputSlot(ItemStack pattern, int slot, FluidStack stack) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().put(String.format(NBT_FLUID_INPUT_SLOT, slot), stack.writeToNBT(new CompoundTag())); } public static FluidStack getFluidInputSlot(ItemStack pattern, int slot) { String id = String.format(NBT_FLUID_INPUT_SLOT, slot); if (!pattern.hasTag() || !pattern.getTag().contains(id)) { return FluidStack.EMPTY; } return FluidStack.loadFluidStackFromNBT(pattern.getTag().getCompound(id)); } public static void setFluidOutputSlot(ItemStack pattern, int slot, FluidStack stack) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().put(String.format(NBT_FLUID_OUTPUT_SLOT, slot), stack.writeToNBT(new CompoundTag())); } public static FluidStack getFluidOutputSlot(ItemStack pattern, int slot) { String id = String.format(NBT_FLUID_OUTPUT_SLOT, slot); if (!pattern.hasTag() || !pattern.getTag().contains(id)) { return FluidStack.EMPTY; } return FluidStack.loadFluidStackFromNBT(pattern.getTag().getCompound(id)); } public static boolean isProcessing(ItemStack pattern) { return pattern.hasTag() && pattern.getTag().contains(NBT_PROCESSING) && pattern.getTag().getBoolean(NBT_PROCESSING); } public static void setProcessing(ItemStack pattern, boolean processing) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().putBoolean(NBT_PROCESSING, processing); } public static boolean isExact(ItemStack pattern) { if (!pattern.hasTag() || !pattern.getTag().contains(NBT_EXACT)) { return false; } return pattern.getTag().getBoolean(NBT_EXACT); } public static void setExact(ItemStack pattern, boolean exact) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().putBoolean(NBT_EXACT, exact); } public static void setToCurrentVersion(ItemStack pattern) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().putInt(NBT_VERSION, VERSION); } public static void setAllowedTags(ItemStack pattern, AllowedTagList allowedTagList) { if (!pattern.hasTag()) { pattern.setTag(new CompoundTag()); } pattern.getTag().put(NBT_ALLOWED_TAGS, allowedTagList.writeToNbt()); } @Nullable public static AllowedTagList getAllowedTags(ItemStack pattern) { if (!pattern.hasTag() || !pattern.getTag().contains(NBT_ALLOWED_TAGS)) { return null; } AllowedTagList allowedTagList = new AllowedTagList(null, GridNetworkNode.PROCESSING_MATRIX_SIZE); allowedTagList.readFromNbt(pattern.getTag().getCompound(NBT_ALLOWED_TAGS)); return allowedTagList; } @Override public void initializeClient(Consumer consumer) { super.initializeClient(consumer); consumer.accept(new IClientItemExtensions() { @Override public BlockEntityWithoutLevelRenderer getCustomRenderer() { return PatternItemBlockEntityRenderer.getInstance(); } }); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (!stack.hasTag() || level == null) { return; } ICraftingPattern pattern = fromCache(level, stack); if (pattern.isValid()) { if (Screen.hasShiftDown() || isProcessing(stack)) { tooltip.add(Component.translatable("misc.refinedstorage.pattern.inputs").setStyle(Styles.YELLOW)); RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getInputs().stream().map(i -> !i.isEmpty() ? i.get(0) : ItemStack.EMPTY).collect(Collectors.toList())); RenderUtils.addCombinedFluidsToTooltip(tooltip, true, pattern.getFluidInputs().stream().map(i -> !i.isEmpty() ? i.get(0) : FluidStack.EMPTY).collect(Collectors.toList())); tooltip.add(Component.translatable("misc.refinedstorage.pattern.outputs").setStyle(Styles.YELLOW)); } RenderUtils.addCombinedItemsToTooltip(tooltip, true, pattern.getOutputs()); RenderUtils.addCombinedFluidsToTooltip(tooltip, true, pattern.getFluidOutputs()); if (pattern instanceof CraftingPattern && ((CraftingPattern) pattern).getAllowedTagList() != null) { addAllowedTags(tooltip, (CraftingPattern) pattern); } if (isExact(stack)) { tooltip.add(Component.translatable("misc.refinedstorage.pattern.exact").setStyle(Styles.BLUE)); } if (isProcessing(stack)) { tooltip.add(Component.translatable("misc.refinedstorage.processing").setStyle(Styles.BLUE)); } } else { tooltip.add(Component.translatable("misc.refinedstorage.pattern.invalid").setStyle(Styles.RED)); tooltip.add(pattern.getErrorMessage().plainCopy().setStyle(Styles.GRAY)); } } public void addAllowedTags(List tooltip, CraftingPattern pattern) { for (int i = 0; i < pattern.getAllowedTagList().getAllowedItemTags().size(); ++i) { Set allowedTags = pattern.getAllowedTagList().getAllowedItemTags().get(i); for (ResourceLocation tag : allowedTags) { tooltip.add(Component.translatable( "misc.refinedstorage.pattern.allowed_item_tag", tag.toString(), pattern.getInputs().get(i).get(0).getHoverName() ).setStyle(Styles.AQUA)); } } for (int i = 0; i < pattern.getAllowedTagList().getAllowedFluidTags().size(); ++i) { Set allowedTags = pattern.getAllowedTagList().getAllowedFluidTags().get(i); for (ResourceLocation tag : allowedTags) { tooltip.add(Component.translatable( "misc.refinedstorage.pattern.allowed_fluid_tag", tag.toString(), pattern.getFluidInputs().get(i).get(0).getDisplayName() ).setStyle(Styles.AQUA)); } } } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { if (!level.isClientSide && player.isCrouching()) { return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.PATTERN.get(), player.getItemInHand(hand).getCount())); } return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand)); } @Override @Nonnull public ICraftingPattern create(Level level, ItemStack stack, ICraftingPatternContainer container) { return CraftingPatternFactory.INSTANCE.create(level, container, stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/ProcessorBindingItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class ProcessorBindingItem extends Item { public ProcessorBindingItem() { super(new Item.Properties()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/ProcessorItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class ProcessorItem extends Item { public ProcessorItem() { super(new Item.Properties()); } public enum Type { RAW_BASIC("raw_basic"), RAW_IMPROVED("raw_improved"), RAW_ADVANCED("raw_advanced"), BASIC("basic"), IMPROVED("improved"), ADVANCED("advanced"); final String name; Type(String name) { this.name = name; } public String getName() { return name; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/QuartzEnrichedIronItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class QuartzEnrichedIronItem extends Item { public QuartzEnrichedIronItem() { super(new Item.Properties()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/SecurityCardItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class SecurityCardItem extends Item { private static final String NBT_OWNER = "Owner"; private static final String NBT_OWNER_NAME = "OwnerName"; private static final String NBT_PERMISSION = "Permission_%d"; public SecurityCardItem() { super(new Item.Properties().stacksTo(1)); } @Nullable public static UUID getOwner(ItemStack stack) { if (stack.hasTag() && stack.getTag().contains(NBT_OWNER)) { return UUID.fromString(stack.getTag().getString(NBT_OWNER)); } return null; } public static boolean hasPermission(ItemStack stack, Permission permission) { String id = String.format(NBT_PERMISSION, permission.getId()); if (stack.hasTag() && stack.getTag().contains(id)) { return stack.getTag().getBoolean(id); } return false; } public static void setPermission(ItemStack stack, Permission permission, boolean state) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putBoolean(String.format(NBT_PERMISSION, permission.getId()), state); } public static boolean isValid(ItemStack stack) { return stack.hasTag() && stack.getTag().contains(NBT_OWNER); } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if (!level.isClientSide) { stack.setTag(new CompoundTag()); stack.getTag().putString(NBT_OWNER, player.getGameProfile().getId().toString()); stack.getTag().putString(NBT_OWNER_NAME, player.getGameProfile().getName()); } return InteractionResultHolder.success(stack); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (stack.hasTag() && stack.getTag().contains(NBT_OWNER_NAME)) { tooltip.add(Component.translatable("item.refinedstorage.security_card.owner", stack.getTag().getString(NBT_OWNER_NAME)).setStyle(Styles.GRAY)); } for (Permission permission : Permission.values()) { if (hasPermission(stack, permission)) { tooltip.add(Component.literal("- ").append(Component.translatable("gui.refinedstorage.security_manager.permission." + permission.getId())).setStyle(Styles.GRAY)); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/SiliconItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class SiliconItem extends Item { public SiliconItem() { super(new Item.Properties()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/StorageDiskItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class StorageDiskItem extends Item implements IStorageDiskProvider { private static final String NBT_ID = "Id"; private final ItemStorageType type; public StorageDiskItem(ItemStorageType type) { super(new Item.Properties().stacksTo(1)); this.type = type; } @Override public void inventoryTick(ItemStack stack, Level level, Entity entity, int slot, boolean selected) { super.inventoryTick(stack, level, entity, slot, selected); if (!level.isClientSide && !stack.hasTag() && entity instanceof Player) { UUID id = UUID.randomUUID(); API.instance().getStorageDiskManager((ServerLevel) level).set(id, API.instance().createDefaultItemDisk((ServerLevel) level, getCapacity(stack), (Player) entity)); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); setId(stack, id); } } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (isValid(stack)) { UUID id = getId(stack); API.instance().getStorageDiskSync().sendRequest(id); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id); if (data != null) { if (data.getCapacity() == -1) { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY)); } else { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored_capacity", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY)); } } if (flag.isAdvanced()) { tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY)); } } } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack diskStack = player.getItemInHand(hand); if (!level.isClientSide && player.isCrouching() && type != ItemStorageType.CREATIVE) { IStorageDisk disk = API.instance().getStorageDiskManager((ServerLevel) level).getByStack(diskStack); if (disk != null && disk.getStored() == 0) { ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type), diskStack.getCount()); if (!player.getInventory().add(storagePart.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart); } API.instance().getStorageDiskManager((ServerLevel) level).remove(getId(diskStack)); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSItems.STORAGE_HOUSING.get())); } } return new InteractionResultHolder<>(InteractionResult.PASS, diskStack); } @Override public int getEntityLifespan(ItemStack stack, Level level) { return Integer.MAX_VALUE; } @Override public UUID getId(ItemStack disk) { return disk.getTag().getUUID(NBT_ID); } @Override public void setId(ItemStack disk, UUID id) { disk.setTag(new CompoundTag()); disk.getTag().putUUID(NBT_ID, id); } @Override public boolean isValid(ItemStack disk) { return disk.hasTag() && disk.getTag().hasUUID(NBT_ID); } @Override public int getCapacity(ItemStack disk) { return type.getCapacity(); } @Override public StorageType getType() { return StorageType.ITEM; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/StorageHousingItem.java ================================================ package com.refinedmods.refinedstorage.item; import net.minecraft.world.item.Item; public class StorageHousingItem extends Item { public StorageHousingItem() { super(new Item.Properties()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/StoragePartItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import net.minecraft.world.item.Item; public class StoragePartItem extends Item { public StoragePartItem() { super(new Item.Properties()); } public static StoragePartItem getByType(ItemStorageType type) { return RSItems.ITEM_STORAGE_PARTS.get(type).get(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/UpgradeItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; public class UpgradeItem extends Item { private final Type type; public UpgradeItem(Type type) { super(new Item.Properties()); this.type = type; } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (type.getFortuneLevel() > 0) { tooltip.add( Component.translatable("enchantment.minecraft.fortune") .append(" ") .append(Component.translatable("enchantment.level." + type.getFortuneLevel())) .setStyle(Styles.GRAY) ); } } @Override public boolean isFoil(ItemStack stack) { return type == Type.SILK_TOUCH || type == Type.FORTUNE_1 || type == Type.FORTUNE_2 || type == Type.FORTUNE_3; } public Type getType() { return type; } public enum Type { NORMAL("normal"), SPEED("speed"), RANGE("range"), CRAFTING("crafting"), STACK("stack"), SILK_TOUCH("silk_touch"), FORTUNE_1("fortune_1"), FORTUNE_2("fortune_2"), FORTUNE_3("fortune_3"), REGULATOR("regulator"); private final String name; Type(String name) { this.name = name; } public String getName() { return name; } public int getEnergyUsage() { switch (this) { case NORMAL: return 0; case RANGE: return RS.SERVER_CONFIG.getUpgrades().getRangeUpgradeUsage(); case SPEED: return RS.SERVER_CONFIG.getUpgrades().getSpeedUpgradeUsage(); case CRAFTING: return RS.SERVER_CONFIG.getUpgrades().getCraftingUpgradeUsage(); case STACK: return RS.SERVER_CONFIG.getUpgrades().getStackUpgradeUsage(); case SILK_TOUCH: return RS.SERVER_CONFIG.getUpgrades().getSilkTouchUpgradeUsage(); case FORTUNE_1: return RS.SERVER_CONFIG.getUpgrades().getFortune1UpgradeUsage(); case FORTUNE_2: return RS.SERVER_CONFIG.getUpgrades().getFortune2UpgradeUsage(); case FORTUNE_3: return RS.SERVER_CONFIG.getUpgrades().getFortune3UpgradeUsage(); case REGULATOR: return RS.SERVER_CONFIG.getUpgrades().getRegulatorUpgradeUsage(); default: throw new IllegalStateException("What even am I?"); } } public int getFortuneLevel() { switch (this) { case FORTUNE_1: return 1; case FORTUNE_2: return 2; case FORTUNE_3: return 3; default: return 0; } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/WirelessCraftingMonitorItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.apiimpl.network.item.WirelessCraftingMonitorNetworkItem; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; import java.util.Optional; import java.util.UUID; public class WirelessCraftingMonitorItem extends NetworkItem { public static final String NBT_TAB_SELECTED = "TabSelected"; public static final String NBT_TAB_PAGE = "TabPage"; private final Type type; public WirelessCraftingMonitorItem(Type type) { super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessCraftingMonitor().getCapacity()); this.type = type; } public static Optional getTabSelected(ItemStack stack) { if (stack.hasTag() && stack.getTag().hasUUID(NBT_TAB_SELECTED)) { return Optional.of(stack.getTag().getUUID(NBT_TAB_SELECTED)); } return Optional.empty(); } public static void setTabSelected(ItemStack stack, Optional tabSelected) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } if (tabSelected.isPresent()) { stack.getTag().putUUID(NBT_TAB_SELECTED, tabSelected.get()); } else { stack.getTag().remove(NBT_TAB_SELECTED + "Least"); stack.getTag().remove(NBT_TAB_SELECTED + "Most"); } } public static int getTabPage(ItemStack stack) { if (stack.hasTag() && stack.getTag().contains(NBT_TAB_PAGE)) { return stack.getTag().getInt(NBT_TAB_PAGE); } return 0; } public static void setTabPage(ItemStack stack, int tabPage) { if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } stack.getTag().putInt(NBT_TAB_PAGE, tabPage); } public Type getType() { return type; } @Nonnull @Override public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { return new WirelessCraftingMonitorNetworkItem(handler, player, stack, slot); } public enum Type { NORMAL, CREATIVE } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/WirelessFluidGridItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.apiimpl.network.item.WirelessFluidGridNetworkItem; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; public class WirelessFluidGridItem extends NetworkItem { private final Type type; public WirelessFluidGridItem(Type type) { super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessFluidGrid().getCapacity()); this.type = type; } public static int getSortingType(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_TYPE) : IGrid.SORTING_TYPE_QUANTITY; } public static int getSortingDirection(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_DIRECTION)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_DIRECTION) : IGrid.SORTING_DIRECTION_DESCENDING; } public static int getSearchBoxMode(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE) : IGrid.SEARCH_BOX_MODE_NORMAL; } public static int getTabSelected(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_SELECTED)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_SELECTED) : -1; } public static int getTabPage(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_PAGE)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_PAGE) : 0; } public static int getSize(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SIZE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SIZE) : IGrid.SIZE_STRETCH; } public Type getType() { return type; } @Nonnull @Override public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { return new WirelessFluidGridNetworkItem(handler, player, stack, slot); } public enum Type { NORMAL, CREATIVE } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/WirelessGridItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.item.INetworkItem; import com.refinedmods.refinedstorage.api.network.item.INetworkItemManager; import com.refinedmods.refinedstorage.apiimpl.network.item.WirelessGridNetworkItem; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import javax.annotation.Nonnull; public class WirelessGridItem extends NetworkItem { private final Type type; public WirelessGridItem(Type type) { super(new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getWirelessGrid().getCapacity()); this.type = type; } public static int getViewType(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_VIEW_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_VIEW_TYPE) : IGrid.VIEW_TYPE_NORMAL; } public static int getSortingType(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_TYPE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_TYPE) : IGrid.SORTING_TYPE_QUANTITY; } public static int getSortingDirection(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SORTING_DIRECTION)) ? stack.getTag().getInt(GridNetworkNode.NBT_SORTING_DIRECTION) : IGrid.SORTING_DIRECTION_DESCENDING; } public static int getSearchBoxMode(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SEARCH_BOX_MODE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SEARCH_BOX_MODE) : IGrid.SEARCH_BOX_MODE_NORMAL; } public static int getTabSelected(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_SELECTED)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_SELECTED) : -1; } public static int getTabPage(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_TAB_PAGE)) ? stack.getTag().getInt(GridNetworkNode.NBT_TAB_PAGE) : 0; } public static int getSize(ItemStack stack) { return (stack.hasTag() && stack.getTag().contains(GridNetworkNode.NBT_SIZE)) ? stack.getTag().getInt(GridNetworkNode.NBT_SIZE) : IGrid.SIZE_STRETCH; } public Type getType() { return type; } @Override @Nonnull public INetworkItem provide(INetworkItemManager handler, Player player, ItemStack stack, PlayerSlot slot) { return new WirelessGridNetworkItem(handler, player, stack, slot); } public enum Type { NORMAL, CREATIVE } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/WrenchItem.java ================================================ package com.refinedmods.refinedstorage.item; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.util.NetworkUtils; import com.refinedmods.refinedstorage.util.LevelUtils; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.items.ItemHandlerHelper; public class WrenchItem extends Item { public WrenchItem() { super(new Item.Properties().stacksTo(1)); } @Override public InteractionResult onItemUseFirst(ItemStack stack, UseOnContext ctx) { if (ctx.getLevel().isClientSide) { return InteractionResult.CONSUME; } INetworkNode node = NetworkUtils.getNodeFromBlockEntity(ctx.getLevel().getBlockEntity(ctx.getClickedPos())); INetwork network = NetworkUtils.getNetworkFromNode(node); if (network != null && !network.getSecurityManager().hasPermission(Permission.BUILD, ctx.getPlayer())) { LevelUtils.sendNoPermissionMessage(ctx.getPlayer()); return InteractionResult.FAIL; } BlockState state = ctx.getLevel().getBlockState(ctx.getClickedPos()); if (node instanceof ICoverable && ((ICoverable) node).getCoverManager().hasCover(ctx.getClickedFace())) { Cover cover = ((ICoverable) node).getCoverManager().removeCover(ctx.getClickedFace()); if (cover != null) { ItemStack stack1 = cover.getType().createStack(); CoverItem.setItem(stack1, cover.getStack()); ItemHandlerHelper.giveItemToPlayer(ctx.getPlayer(), stack1); ctx.getLevel().sendBlockUpdated(ctx.getClickedPos(), state, state, 3); ctx.getLevel().updateNeighborsAt(ctx.getClickedPos(), ctx.getLevel().getBlockState(ctx.getClickedPos()).getBlock()); return InteractionResult.SUCCESS; } } ctx.getLevel().setBlockAndUpdate(ctx.getClickedPos(), state.rotate(ctx.getLevel(), ctx.getClickedPos(), Rotation.CLOCKWISE_90)); return InteractionResult.CONSUME; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/BaseBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.block.BlockDirection; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.block.state.BlockState; public class BaseBlockItem extends BlockItem { private final BaseBlock block; public BaseBlockItem(BaseBlock block, Properties builder) { super(block, builder); this.block = block; } @Override protected boolean placeBlock(BlockPlaceContext context, BlockState state) { boolean result = super.placeBlock(context, state); if (result && block.getDirection() != BlockDirection.NONE) { context.getLevel().setBlockAndUpdate(context.getClickedPos(), state.setValue(block.getDirection().getProperty(), block.getDirection().getFrom( context.getClickedFace(), context.getClickedPos(), context.getPlayer() ))); } return result; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/ColoredBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.network.chat.Component; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; public class ColoredBlockItem extends BaseBlockItem { private final Component displayName; public ColoredBlockItem(BaseBlock block, Properties builder, DyeColor color, Component displayName) { super(block, builder); if (color != ColorMap.DEFAULT_COLOR) { this.displayName = Component.translatable("color.minecraft." + color.getName()) .append(" ") .append(displayName); } else { this.displayName = displayName; } } @Override public Component getName(ItemStack stack) { return displayName; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/ControllerBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.NetworkType; import com.refinedmods.refinedstorage.block.ControllerBlock; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.network.chat.Component; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; public class ControllerBlockItem extends EnergyBlockItem { private final Component displayName; public ControllerBlockItem(ControllerBlock block, DyeColor color, Component displayName) { super(block, new Item.Properties().stacksTo(1), block.getType() == NetworkType.CREATIVE, () -> RS.SERVER_CONFIG.getController().getCapacity()); if (color != ColorMap.DEFAULT_COLOR) { this.displayName = Component.translatable("color.minecraft." + color.getName()) .append(" ") .append(displayName); } else { this.displayName = displayName; } } @Override public Component getName(ItemStack stack) { return displayName; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/EnergyBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.energy.ItemEnergyStorage; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.util.Mth; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import javax.annotation.Nullable; import java.util.List; import java.util.function.Supplier; public abstract class EnergyBlockItem extends BaseBlockItem { private final Supplier energyCapacity; private final boolean creative; protected EnergyBlockItem(BaseBlock block, Item.Properties properties, boolean creative, Supplier energyCapacity) { super(block, properties); this.creative = creative; this.energyCapacity = energyCapacity; } public EnergyStorage createEnergyStorage(ItemStack stack) { return new ItemEnergyStorage(stack, energyCapacity.get()); } @Override public boolean isBarVisible(ItemStack stack) { return !creative; } @Override public int getBarWidth(ItemStack stack) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return 0; } float stored = (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored(); return Math.round(stored * 13F); } @Override public int getBarColor(ItemStack stack) { IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return super.getBarColor(stack); } return Mth.hsvToRgb(Math.max(0.0F, (float) energy.getEnergyStored() / (float) energy.getMaxEnergyStored()) / 3.0F, 1.0F, 1.0F); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (!creative) { final IEnergyStorage energy = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energy == null) { return; } tooltip.add(Component.translatable("misc.refinedstorage.energy_stored", energy.getEnergyStored(), energy.getMaxEnergyStored()).setStyle(Styles.GRAY)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/FluidStorageBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.block.FluidStorageBlock; import com.refinedmods.refinedstorage.item.FluidStoragePartItem; import com.refinedmods.refinedstorage.item.ProcessorItem; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class FluidStorageBlockItem extends BaseBlockItem { private final FluidStorageType type; public FluidStorageBlockItem(FluidStorageBlock block) { super(block, new Item.Properties()); this.type = block.getType(); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (isValid(stack)) { UUID id = getId(stack); API.instance().getStorageDiskSync().sendRequest(id); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id); if (data != null) { if (data.getCapacity() == -1) { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY)); } else { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored_capacity", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY)); } } if (flag.isAdvanced()) { tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY)); } } } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack storageStack = player.getItemInHand(hand); if (!level.isClientSide && player.isCrouching() && type != FluidStorageType.CREATIVE) { UUID diskId = null; IStorageDisk disk = null; if (isValid(storageStack)) { diskId = getId(storageStack); disk = API.instance().getStorageDiskManager((ServerLevel) level).get(diskId); } // Newly created fluid storages won't have a tag yet, so allow invalid disks as well. if (disk == null || disk.getStored() == 0) { ItemStack fluidStoragePart = new ItemStack(FluidStoragePartItem.getByType(type)); if (!player.getInventory().add(fluidStoragePart.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), fluidStoragePart); } ItemStack processor = new ItemStack(RSItems.PROCESSORS.get(ProcessorItem.Type.BASIC).get()); if (!player.getInventory().add(processor.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), processor); } ItemStack bucket = new ItemStack(Items.BUCKET); if (!player.getInventory().add(bucket.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), bucket); } if (disk != null) { API.instance().getStorageDiskManager((ServerLevel) level).remove(diskId); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); } return new InteractionResultHolder<>(InteractionResult.SUCCESS, new ItemStack(RSBlocks.MACHINE_CASING.get())); } } return new InteractionResultHolder<>(InteractionResult.PASS, storageStack); } @Override public int getEntityLifespan(ItemStack stack, Level level) { return Integer.MAX_VALUE; } private UUID getId(ItemStack disk) { return disk.getTag().getUUID(FluidStorageNetworkNode.NBT_ID); } private boolean isValid(ItemStack disk) { return disk.hasTag() && disk.getTag().hasUUID(FluidStorageNetworkNode.NBT_ID); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/PortableGridBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.WirelessGridItem; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; public class PortableGridBlockItem extends EnergyBlockItem { private final Type type; public PortableGridBlockItem(Type type) { super( type == Type.CREATIVE ? RSBlocks.CREATIVE_PORTABLE_GRID.get() : RSBlocks.PORTABLE_GRID.get(), new Item.Properties().stacksTo(1), type == Type.CREATIVE, () -> RS.SERVER_CONFIG.getPortableGrid().getCapacity() ); this.type = type; } public Type getType() { return type; } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack stack = player.getItemInHand(hand); if (!level.isClientSide) { API.instance().getGridManager().openGrid(PortableGridGridFactory.ID, (ServerPlayer) player, stack, PlayerSlot.getSlotForHand(player, hand)); } return InteractionResultHolder.success(stack); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); tooltip.add(Component.translatable("block.refinedstorage.portable_grid.tooltip").setStyle(Styles.GRAY)); } @Override public InteractionResult useOn(UseOnContext context) { if (context.getPlayer() == null) { return InteractionResult.FAIL; } //Place if (context.getPlayer().isCrouching()) { return super.useOn(context); } ItemStack stack = context.getPlayer().getItemInHand(context.getHand()); if (!context.getLevel().isClientSide) { API.instance().getGridManager().openGrid(PortableGridGridFactory.ID, (ServerPlayer) context.getPlayer(), stack, PlayerSlot.getSlotForHand(context.getPlayer(), context.getHand())); } return InteractionResult.SUCCESS; } @Override public int getEntityLifespan(ItemStack stack, Level level) { return Integer.MAX_VALUE; } @Override public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) { if (oldStack.getItem() == newStack.getItem() && WirelessGridItem.getSortingDirection(oldStack) == WirelessGridItem.getSortingDirection(newStack) && WirelessGridItem.getSortingType(oldStack) == WirelessGridItem.getSortingType(newStack) && WirelessGridItem.getSearchBoxMode(oldStack) == WirelessGridItem.getSearchBoxMode(newStack) && WirelessGridItem.getTabSelected(oldStack) == WirelessGridItem.getTabSelected(newStack) && WirelessGridItem.getTabPage(oldStack) == WirelessGridItem.getTabPage(newStack) && WirelessGridItem.getSize(oldStack) == WirelessGridItem.getSize(newStack)) { return false; } return super.shouldCauseReequipAnimation(oldStack, newStack, slotChanged); } public enum Type { NORMAL, CREATIVE } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/blockitem/StorageBlockItem.java ================================================ package com.refinedmods.refinedstorage.item.blockitem; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.block.StorageBlock; import com.refinedmods.refinedstorage.item.StoragePartItem; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.Level; import javax.annotation.Nullable; import java.util.List; import java.util.UUID; public class StorageBlockItem extends BaseBlockItem { private final ItemStorageType type; public StorageBlockItem(StorageBlock block) { super(block, new Item.Properties()); this.type = block.getType(); } @Override public void appendHoverText(ItemStack stack, @Nullable Level level, List tooltip, TooltipFlag flag) { super.appendHoverText(stack, level, tooltip, flag); if (isValid(stack)) { UUID id = getId(stack); API.instance().getStorageDiskSync().sendRequest(id); StorageDiskSyncData data = API.instance().getStorageDiskSync().getData(id); if (data != null) { if (data.getCapacity() == -1) { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored", API.instance().getQuantityFormatter().format(data.getStored())).setStyle(Styles.GRAY)); } else { tooltip.add(Component.translatable("misc.refinedstorage.storage.stored_capacity", API.instance().getQuantityFormatter().format(data.getStored()), API.instance().getQuantityFormatter().format(data.getCapacity())).setStyle(Styles.GRAY)); } } if (flag.isAdvanced()) { tooltip.add(Component.literal(id.toString()).setStyle(Styles.GRAY)); } } } @Override public InteractionResultHolder use(Level level, Player player, InteractionHand hand) { ItemStack storageStack = player.getItemInHand(hand); int count = storageStack.getCount(); if (!level.isClientSide && player.isCrouching() && type != ItemStorageType.CREATIVE) { UUID diskId = null; IStorageDisk disk = null; if (isValid(storageStack)) { diskId = getId(storageStack); disk = API.instance().getStorageDiskManager((ServerLevel) level).get(diskId); } // Newly created storages won't have a tag yet, so allow invalid disks as well. if (disk == null || disk.getStored() == 0) { ItemStack storagePart = new ItemStack(StoragePartItem.getByType(type)); storagePart.setCount(count); if (!player.getInventory().add(storagePart.copy())) { Containers.dropItemStack(level, player.getX(), player.getY(), player.getZ(), storagePart); } if (disk != null) { API.instance().getStorageDiskManager((ServerLevel) level).remove(diskId); API.instance().getStorageDiskManager((ServerLevel) level).markForSaving(); } ItemStack stack = new ItemStack(RSBlocks.MACHINE_CASING.get()); stack.setCount(count); return new InteractionResultHolder<>(InteractionResult.SUCCESS, stack); } } return new InteractionResultHolder<>(InteractionResult.PASS, storageStack); } @Override public int getEntityLifespan(ItemStack stack, Level level) { return Integer.MAX_VALUE; } private UUID getId(ItemStack disk) { return disk.getTag().getUUID(StorageNetworkNode.NBT_ID); } private boolean isValid(ItemStack disk) { return disk.hasTag() && disk.getTag().hasUUID(StorageNetworkNode.NBT_ID); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/property/ControllerItemPropertyGetter.java ================================================ package com.refinedmods.refinedstorage.item.property; import com.refinedmods.refinedstorage.apiimpl.network.Network; import com.refinedmods.refinedstorage.block.ControllerBlock; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; import net.minecraft.client.renderer.item.ItemPropertyFunction; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; import javax.annotation.Nullable; public class ControllerItemPropertyGetter implements ItemPropertyFunction { @Override public float call(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { // if that stack is still clean (like in the creative mode tab, or just crafted) maintain the on state. if (stack.getTag() == null) { return ControllerBlock.EnergyType.ON.ordinal(); } IEnergyStorage storage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (storage != null) { return Network.getEnergyType(storage.getEnergyStored(), storage.getMaxEnergyStored()).ordinal(); } return ControllerBlock.EnergyType.ON.ordinal(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/property/NetworkItemPropertyGetter.java ================================================ package com.refinedmods.refinedstorage.item.property; import com.refinedmods.refinedstorage.item.NetworkItem; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; import net.minecraft.client.renderer.item.ItemPropertyFunction; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; public class NetworkItemPropertyGetter implements ClampedItemPropertyFunction { @Override public float unclampedCall(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { return entity != null && NetworkItem.isValid(stack) ? 1.0f : 0.0f; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/item/property/SecurityCardItemPropertyGetter.java ================================================ package com.refinedmods.refinedstorage.item.property; import com.refinedmods.refinedstorage.item.SecurityCardItem; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.item.ClampedItemPropertyFunction; import net.minecraft.client.renderer.item.ItemPropertyFunction; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import javax.annotation.Nullable; public class SecurityCardItemPropertyGetter implements ClampedItemPropertyFunction { @Override public float unclampedCall(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { return entity != null && SecurityCardItem.isValid(stack) ? 1.0f : 0.0f; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/loottable/ControllerLootFunction.java ================================================ package com.refinedmods.refinedstorage.loottable; import com.refinedmods.refinedstorage.RSLootFunctions; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.energy.IEnergyStorage; public class ControllerLootFunction implements LootItemFunction { @Override public LootItemFunctionType getType() { return RSLootFunctions.CONTROLLER; } @Override public ItemStack apply(ItemStack stack, LootContext lootContext) { BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); if (blockEntity instanceof ControllerBlockEntity) { INetwork network = ((ControllerBlockEntity) blockEntity).getRemovedNetwork() == null ? ((ControllerBlockEntity) blockEntity).getNetwork() : ((ControllerBlockEntity) blockEntity).getRemovedNetwork(); IEnergyStorage energyStorage = stack.getCapability(Capabilities.EnergyStorage.ITEM); if (energyStorage != null) { energyStorage.receiveEnergy(network.getEnergyStorage().getEnergyStored(), false); } } return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/loottable/CrafterLootFunction.java ================================================ package com.refinedmods.refinedstorage.loottable; import com.refinedmods.refinedstorage.RSLootFunctions; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode; import com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; public class CrafterLootFunction implements LootItemFunction { @Override public LootItemFunctionType getType() { return RSLootFunctions.CRAFTER; } @Override public ItemStack apply(ItemStack stack, LootContext lootContext) { BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); CrafterNetworkNode removedNode = ((CrafterBlockEntity) blockEntity).getRemovedNode(); if (removedNode == null) { removedNode = ((CrafterBlockEntity) blockEntity).getNode(); } if (removedNode.getDisplayName() != null) { stack.setHoverName(removedNode.getDisplayName()); } return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/loottable/PortableGridBlockLootFunction.java ================================================ package com.refinedmods.refinedstorage.loottable; import com.refinedmods.refinedstorage.RSLootFunctions; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; public class PortableGridBlockLootFunction implements LootItemFunction { @Override public LootItemFunctionType getType() { return RSLootFunctions.PORTABLE_GRID; } @Override public ItemStack apply(ItemStack stack, LootContext lootContext) { BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); if (blockEntity instanceof PortableGridBlockEntity) { ((PortableGridBlockEntity) blockEntity).applyDataFromBlockEntityToItem(stack); } return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/loottable/StorageBlockLootFunction.java ================================================ package com.refinedmods.refinedstorage.loottable; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import com.refinedmods.refinedstorage.RSLootFunctions; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.StorageBlockEntity; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.storage.loot.LootContext; import net.minecraft.world.level.storage.loot.functions.LootItemConditionalFunction; import net.minecraft.world.level.storage.loot.functions.LootItemFunction; import net.minecraft.world.level.storage.loot.functions.LootItemFunctionType; import net.minecraft.world.level.storage.loot.parameters.LootContextParams; import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; public class StorageBlockLootFunction implements LootItemFunction { @Override public LootItemFunctionType getType() { return RSLootFunctions.STORAGE_BLOCK; } @Override public ItemStack apply(ItemStack stack, LootContext lootContext) { BlockEntity blockEntity = lootContext.getParamOrNull(LootContextParams.BLOCK_ENTITY); // This code needs to work without the node being removed as well. // For example: the Destructor calls getDrops before the node has been removed. if (blockEntity instanceof StorageBlockEntity) { StorageNetworkNode removedNode = ((StorageBlockEntity) blockEntity).getRemovedNode(); if (removedNode == null) { removedNode = ((StorageBlockEntity) blockEntity).getNode(); } stack.setTag(new CompoundTag()); stack.getTag().putUUID(StorageNetworkNode.NBT_ID, removedNode.getStorageId()); } else if (blockEntity instanceof FluidStorageBlockEntity) { FluidStorageNetworkNode removedNode = ((FluidStorageBlockEntity) blockEntity).getRemovedNode(); if (removedNode == null) { removedNode = ((FluidStorageBlockEntity) blockEntity).getNode(); } stack.setTag(new CompoundTag()); stack.getTag().putUUID(FluidStorageNetworkNode.NBT_ID, removedNode.getStorageId()); } return stack; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/ClientProxy.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.CraftingMonitorScreen; import com.refinedmods.refinedstorage.screen.grid.CraftingPreviewScreen; import com.refinedmods.refinedstorage.screen.grid.CraftingSettingsScreen; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; public class ClientProxy { private ClientProxy() { } public static void onReceivedCraftingPreviewResponseMessage(GridCraftingPreviewResponseMessage message) { Screen parent = Minecraft.getInstance().screen; if (parent instanceof CraftingSettingsScreen) { parent = ((CraftingSettingsScreen) parent).getParent(); } Minecraft.getInstance().setScreen(new CraftingPreviewScreen( parent, message.getElements(), message.getId(), message.getQuantity(), message.isFluids(), Component.translatable("gui.refinedstorage.crafting_preview"), Minecraft.getInstance().player.getInventory() )); } public static void onReceivedCraftingStartResponseMessage() { Screen screen = Minecraft.getInstance().screen; if (screen instanceof CraftingSettingsScreen) { ((CraftingSettingsScreen) screen).close(); } } public static void onReceivedCraftingMonitorUpdateMessage(CraftingMonitorUpdateMessage message) { BaseScreen.executeLater(CraftingMonitorScreen.class, craftingMonitor -> craftingMonitor.setTasks(message.getTasks())); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/FilterUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.FilterContainerMenu; import com.refinedmods.refinedstorage.item.FilterItem; import com.refinedmods.refinedstorage.util.PacketBufferUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class FilterUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "filter_update"); private final int compare; private final int mode; private final boolean modFilter; private final String name; private final int type; public FilterUpdateMessage(int compare, int mode, boolean modFilter, String name, int type) { this.compare = compare; this.mode = mode; this.modFilter = modFilter; this.name = name; this.type = type; } public static FilterUpdateMessage decode(FriendlyByteBuf buf) { return new FilterUpdateMessage( buf.readInt(), buf.readInt(), buf.readBoolean(), PacketBufferUtils.readString(buf), buf.readInt() ); } public static void handle(FilterUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { FilterItem.setCompare(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.compare); FilterItem.setMode(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.mode); FilterItem.setModFilter(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.modFilter); FilterItem.setName(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.name); FilterItem.setType(((FilterContainerMenu) player.containerMenu).getFilterItem(), message.type); })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(compare); buf.writeInt(mode); buf.writeBoolean(modFilter); buf.writeUtf(name); buf.writeInt(type); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/FluidFilterSlotUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.Slot; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class FluidFilterSlotUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "fluid_filter_update"); private final int containerSlot; private final FluidStack stack; public FluidFilterSlotUpdateMessage(int containerSlot, FluidStack stack) { this.containerSlot = containerSlot; this.stack = stack; } public static FluidFilterSlotUpdateMessage decode(FriendlyByteBuf buf) { return new FluidFilterSlotUpdateMessage(buf.readInt(), FluidStack.readFromPacket(buf)); } public static void handle(FluidFilterSlotUpdateMessage message, PlayPayloadContext ctx) { BaseScreen.executeLater(gui -> { if (message.containerSlot >= 0 && message.containerSlot < gui.getMenu().slots.size()) { Slot slot = gui.getMenu().getSlot(message.containerSlot); if (slot instanceof FluidFilterSlot) { ((FluidFilterSlot) slot).getFluidInventory().setFluid(slot.getSlotIndex(), message.stack); } } }); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(containerSlot); stack.writeToPacket(buf); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/NetworkHandler.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorCancelMessage; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorUpdateMessage; import com.refinedmods.refinedstorage.network.craftingmonitor.WirelessCraftingMonitorSettingsUpdateMessage; import com.refinedmods.refinedstorage.network.disk.StorageDiskSizeRequestMessage; import com.refinedmods.refinedstorage.network.disk.StorageDiskSizeResponseMessage; import com.refinedmods.refinedstorage.network.grid.GridClearMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewResponseMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingStartRequestMessage; import com.refinedmods.refinedstorage.network.grid.GridCraftingStartResponseMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidInsertHeldMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidPullMessage; import com.refinedmods.refinedstorage.network.grid.GridFluidUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridItemDeltaMessage; import com.refinedmods.refinedstorage.network.grid.GridItemGridScrollMessage; import com.refinedmods.refinedstorage.network.grid.GridItemInsertHeldMessage; import com.refinedmods.refinedstorage.network.grid.GridItemInventoryScrollMessage; import com.refinedmods.refinedstorage.network.grid.GridItemPullMessage; import com.refinedmods.refinedstorage.network.grid.GridItemUpdateMessage; import com.refinedmods.refinedstorage.network.grid.GridPatternCreateMessage; import com.refinedmods.refinedstorage.network.grid.GridProcessingTransferMessage; import com.refinedmods.refinedstorage.network.grid.GridTransferMessage; import com.refinedmods.refinedstorage.network.grid.PortableGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.network.grid.WirelessFluidGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.network.grid.WirelessGridSettingsUpdateMessage; import com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterMessage; import com.refinedmods.refinedstorage.network.sync.BlockEntitySynchronizationParameterUpdateMessage; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.common.util.FakePlayer; import net.neoforged.neoforge.network.PacketDistributor; import net.neoforged.neoforge.network.registration.IPayloadRegistrar; public class NetworkHandler { public void register(IPayloadRegistrar registrar) { registrar.play( StorageDiskSizeRequestMessage.ID, StorageDiskSizeRequestMessage::decode, handler -> handler.server(StorageDiskSizeRequestMessage::handle) ); registrar.play( StorageDiskSizeResponseMessage.ID, StorageDiskSizeResponseMessage::decode, handler -> handler.client(StorageDiskSizeResponseMessage::handle) ); registrar.play( FilterUpdateMessage.ID, FilterUpdateMessage::decode, handler -> handler.server(FilterUpdateMessage::handle) ); registrar.play( FluidFilterSlotUpdateMessage.ID, FluidFilterSlotUpdateMessage::decode, handler -> handler.client(FluidFilterSlotUpdateMessage::handle) ); registrar.play( BlockEntitySynchronizationParameterMessage.ID, BlockEntitySynchronizationParameterMessage::decode, handler -> handler.client(BlockEntitySynchronizationParameterMessage::handle) ); registrar.play( BlockEntitySynchronizationParameterUpdateMessage.ID, BlockEntitySynchronizationParameterUpdateMessage::decode, handler -> handler.server(BlockEntitySynchronizationParameterUpdateMessage::handle) ); registrar.play( GridItemUpdateMessage.ID, GridItemUpdateMessage::decode, handler -> handler.client(GridItemUpdateMessage::handle) ); registrar.play( GridItemDeltaMessage.ID, GridItemDeltaMessage::decode, handler -> handler.client(GridItemDeltaMessage::handle) ); registrar.play( GridItemPullMessage.ID, GridItemPullMessage::decode, handler -> handler.server(GridItemPullMessage::handle) ); registrar.play( GridItemGridScrollMessage.ID, GridItemGridScrollMessage::decode, handler -> handler.server(GridItemGridScrollMessage::handle) ); registrar.play( GridItemInventoryScrollMessage.ID, GridItemInventoryScrollMessage::decode, handler -> handler.server(GridItemInventoryScrollMessage::handle) ); registrar.play( GridItemInsertHeldMessage.ID, GridItemInsertHeldMessage::decode, handler -> handler.server(GridItemInsertHeldMessage::handle) ); registrar.play( GridClearMessage.ID, ctx -> new GridClearMessage(), handler -> handler.server(GridClearMessage::handle) ); registrar.play( GridPatternCreateMessage.ID, GridPatternCreateMessage::decode, handler -> handler.server(GridPatternCreateMessage::handle) ); registrar.play( SetFilterSlotMessage.ID, SetFilterSlotMessage::decode, handler -> handler.server(SetFilterSlotMessage::handle) ); registrar.play( SetFluidFilterSlotMessage.ID, SetFluidFilterSlotMessage::decode, handler -> handler.server(SetFluidFilterSlotMessage::handle) ); registrar.play( GridFluidUpdateMessage.ID, GridFluidUpdateMessage::decode, handler -> handler.client(GridFluidUpdateMessage::handle) ); registrar.play( GridFluidDeltaMessage.ID, GridFluidDeltaMessage::decode, handler -> handler.client(GridFluidDeltaMessage::handle) ); registrar.play( GridFluidInsertHeldMessage.ID, ctx -> new GridFluidInsertHeldMessage(), handler -> handler.server(GridFluidInsertHeldMessage::handle) ); registrar.play( GridFluidPullMessage.ID, GridFluidPullMessage::decode, handler -> handler.server(GridFluidPullMessage::handle) ); registrar.play( GridTransferMessage.ID, GridTransferMessage::decode, handler -> handler.server(GridTransferMessage::handle) ); registrar.play( GridProcessingTransferMessage.ID, GridProcessingTransferMessage::decode, handler -> handler.server(GridProcessingTransferMessage::handle) ); registrar.play( SecurityManagerUpdateMessage.ID, SecurityManagerUpdateMessage::decode, handler -> handler.server(SecurityManagerUpdateMessage::handle) ); registrar.play( WirelessGridSettingsUpdateMessage.ID, WirelessGridSettingsUpdateMessage::decode, handler -> handler.server(WirelessGridSettingsUpdateMessage::handle) ); registrar.play( OpenNetworkItemMessage.ID, OpenNetworkItemMessage::decode, handler -> handler.server(OpenNetworkItemMessage::handle) ); registrar.play( WirelessFluidGridSettingsUpdateMessage.ID, WirelessFluidGridSettingsUpdateMessage::decode, handler -> handler.server(WirelessFluidGridSettingsUpdateMessage::handle) ); registrar.play( PortableGridSettingsUpdateMessage.ID, PortableGridSettingsUpdateMessage::decode, handler -> handler.server(PortableGridSettingsUpdateMessage::handle) ); registrar.play( GridCraftingPreviewRequestMessage.ID, GridCraftingPreviewRequestMessage::decode, handler -> handler.server(GridCraftingPreviewRequestMessage::handle) ); registrar.play( GridCraftingPreviewResponseMessage.ID, GridCraftingPreviewResponseMessage::decode, handler -> handler.client(GridCraftingPreviewResponseMessage::handle) ); registrar.play( GridCraftingStartRequestMessage.ID, GridCraftingStartRequestMessage::decode, handler -> handler.server(GridCraftingStartRequestMessage::handle) ); registrar.play( GridCraftingStartResponseMessage.ID, buf -> new GridCraftingStartResponseMessage(), handler -> handler.client(GridCraftingStartResponseMessage::handle) ); registrar.play( CraftingMonitorUpdateMessage.ID, CraftingMonitorUpdateMessage::decode, handler -> handler.client(CraftingMonitorUpdateMessage::handle) ); registrar.play( CraftingMonitorCancelMessage.ID, CraftingMonitorCancelMessage::decode, handler -> handler.server(CraftingMonitorCancelMessage::handle) ); registrar.play( WirelessCraftingMonitorSettingsUpdateMessage.ID, WirelessCraftingMonitorSettingsUpdateMessage::decode, handler -> handler.server(WirelessCraftingMonitorSettingsUpdateMessage::handle) ); } public void sendTo(ServerPlayer player, CustomPacketPayload message) { if (!(player instanceof FakePlayer)) { PacketDistributor.PLAYER.with(player).send(message); } } public void sendToServer(CustomPacketPayload message) { PacketDistributor.SERVER.noArg().send(message); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/OpenNetworkItemMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.item.NetworkItem; import com.refinedmods.refinedstorage.item.blockitem.PortableGridBlockItem; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class OpenNetworkItemMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "open_network_item"); private final PlayerSlot slot; public OpenNetworkItemMessage(PlayerSlot slot) { this.slot = slot; } public static OpenNetworkItemMessage decode(FriendlyByteBuf buf) { return new OpenNetworkItemMessage(new PlayerSlot(buf)); } public static void handle(OpenNetworkItemMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { ItemStack stack = message.slot.getStackFromSlot(player); if (stack == null) { return; } if (stack.getItem() instanceof NetworkItem) { ((NetworkItem) stack.getItem()).applyNetwork(player.getServer(), stack, n -> n.getNetworkItemManager().open(player, stack, message.slot), player::sendSystemMessage); } else if (stack.getItem() instanceof PortableGridBlockItem) { API.instance().getGridManager() .openGrid(PortableGridGridFactory.ID, (ServerPlayer) player, stack, message.slot); } })); } @Override public void write(FriendlyByteBuf buf) { slot.writePlayerSlot(buf); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/SecurityManagerUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity; import com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class SecurityManagerUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "security_manager_update"); private final Permission permission; private final boolean state; public SecurityManagerUpdateMessage(Permission permission, boolean state) { this.permission = permission; this.state = state; } public static SecurityManagerUpdateMessage decode(FriendlyByteBuf buf) { int id = buf.readInt(); Permission permission = Permission.INSERT; for (Permission otherPermission : Permission.values()) { if (otherPermission.getId() == id) { permission = otherPermission; break; } } boolean state = buf.readBoolean(); return new SecurityManagerUpdateMessage(permission, state); } public static void handle(SecurityManagerUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof SecurityManagerContainerMenu securityManagerContainerMenu) { securityManagerContainerMenu.updatePermission(message.permission, message.state); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(permission.getId()); buf.writeBoolean(state); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/SetFilterSlotMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.legacy.LegacyFilterSlot; import java.util.HashSet; import java.util.Set; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class SetFilterSlotMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "set_filter_slot"); private final int containerSlot; private final ItemStack stack; public SetFilterSlotMessage(int containerSlot, ItemStack stack) { this.containerSlot = containerSlot; this.stack = stack; } public static SetFilterSlotMessage decode(FriendlyByteBuf buf) { return new SetFilterSlotMessage(buf.readInt(), buf.readItem()); } public static void handle(SetFilterSlotMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (!message.stack.isEmpty() && message.stack.getCount() <= message.stack.getMaxStackSize()) { AbstractContainerMenu container = player.containerMenu; if (container != null && message.containerSlot >= 0 && message.containerSlot < container.slots.size()) { handle(message, container); } } })); } private static void handle(SetFilterSlotMessage message, AbstractContainerMenu container) { Slot slot = container.getSlot(message.containerSlot); if (slot instanceof FilterSlot || slot instanceof LegacyFilterSlot) { Runnable postAction = () -> { }; // Prevent the grid crafting matrix inventory listener from resetting the list. if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); //exclude output slots if (grid instanceof GridNetworkNode && slot.getSlotIndex() < ((GridNetworkNode) grid).getAllowedTagList().getAllowedItemTags().size()) { Set list = new HashSet<>( ((GridNetworkNode) grid).getAllowedTagList().getAllowedItemTags().get(slot.getSlotIndex())); postAction = () -> { ((GridNetworkNode) grid).getAllowedTagList().setAllowedItemTags(slot.getSlotIndex(), list); ((GridNetworkNode) grid).markDirty(); }; } } slot.set(message.stack); postAction.run(); } } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(containerSlot); buf.writeItem(stack); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/SetFluidFilterSlotMessage.java ================================================ package com.refinedmods.refinedstorage.network; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import java.util.HashSet; import java.util.Set; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class SetFluidFilterSlotMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "set_fluid_filter_slot"); private final int containerSlot; private final FluidStack stack; public SetFluidFilterSlotMessage(int containerSlot, FluidStack stack) { this.containerSlot = containerSlot; this.stack = stack; } public static SetFluidFilterSlotMessage decode(FriendlyByteBuf buf) { return new SetFluidFilterSlotMessage(buf.readInt(), FluidStack.readFromPacket(buf)); } public static void handle(SetFluidFilterSlotMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (!message.stack.isEmpty() && container != null && message.containerSlot >= 0 && message.containerSlot < container.slots.size()) { handle(message, container); } })); } private static void handle(SetFluidFilterSlotMessage message, AbstractContainerMenu container) { Slot slot = container.getSlot(message.containerSlot); if (slot instanceof FluidFilterSlot) { Runnable postAction = () -> { }; // Prevent the grid crafting matrix inventory listener from resetting the list. if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (grid instanceof GridNetworkNode && slot.getSlotIndex() < ((GridNetworkNode) grid).getAllowedTagList().getAllowedFluidTags().size()) { Set list = new HashSet<>( ((GridNetworkNode) grid).getAllowedTagList().getAllowedFluidTags().get(slot.getSlotIndex())); postAction = () -> { ((GridNetworkNode) grid).getAllowedTagList().setAllowedFluidTags(slot.getSlotIndex(), list); ((GridNetworkNode) grid).markDirty(); }; } } FluidFilterSlot fluidSlot = (FluidFilterSlot) slot; fluidSlot.getFluidInventory().setFluid(slot.getSlotIndex(), message.stack); postAction.run(); } } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(containerSlot); stack.writeToPacket(buf); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorCancelMessage.java ================================================ package com.refinedmods.refinedstorage.network.craftingmonitor; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import java.util.UUID; import javax.annotation.Nullable; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class CraftingMonitorCancelMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "crafting_monitor_cancel"); @Nullable private final UUID taskId; public CraftingMonitorCancelMessage(@Nullable UUID taskId) { this.taskId = taskId; } public static CraftingMonitorCancelMessage decode(FriendlyByteBuf buf) { return new CraftingMonitorCancelMessage(buf.readBoolean() ? buf.readUUID() : null); } public static void handle(CraftingMonitorCancelMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof CraftingMonitorContainerMenu) { ((CraftingMonitorContainerMenu) player.containerMenu).getCraftingMonitor().onCancelled( (ServerPlayer) player, message.taskId ); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeBoolean(taskId != null); if (taskId != null) { buf.writeUUID(taskId); } } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorSyncTask.java ================================================ package com.refinedmods.refinedstorage.network.craftingmonitor; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import java.util.List; import java.util.UUID; public record CraftingMonitorSyncTask(UUID id, ICraftingRequestInfo requestInfo, int quantity, long startTime, int completionPercentage, List elements) { } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/CraftingMonitorUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.craftingmonitor; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.task.CraftingTaskReadException; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingTask; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor; import com.refinedmods.refinedstorage.network.ClientProxy; import com.refinedmods.refinedstorage.screen.CraftingMonitorScreen; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.Function; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class CraftingMonitorUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "crafting_monitor_update"); private static final Logger LOGGER = LogManager.getLogger(CraftingMonitorUpdateMessage.class); private final List tasks; public CraftingMonitorUpdateMessage(List tasks) { this.tasks = tasks; } public static CraftingMonitorUpdateMessage decode(FriendlyByteBuf buf) { int size = buf.readInt(); List tasks = new ArrayList<>(); for (int i = 0; i < size; ++i) { UUID id = buf.readUUID(); ICraftingRequestInfo requested = null; try { requested = API.instance().createCraftingRequestInfo(buf.readNbt()); } catch (CraftingTaskReadException e) { LOGGER.error("Could not create crafting request info", e); } int qty = buf.readInt(); long executionStarted = buf.readLong(); int percentage = buf.readInt(); List elements = new ArrayList<>(); int elementCount = buf.readInt(); for (int j = 0; j < elementCount; ++j) { Function factory = API.instance().getCraftingMonitorElementRegistry().get(buf.readResourceLocation()); if (factory != null) { elements.add(factory.apply(buf)); } } tasks.add(new CraftingMonitorSyncTask(id, requested, qty, executionStarted, percentage, elements)); } return new CraftingMonitorUpdateMessage(tasks); } public static void handle(CraftingMonitorUpdateMessage message, PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> ClientProxy.onReceivedCraftingMonitorUpdateMessage(message)); } public List getTasks() { return tasks; } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(tasks.size()); for (CraftingMonitorSyncTask task : tasks) { buf.writeUUID(task.id()); buf.writeNbt(task.requestInfo().writeToNbt()); buf.writeInt(task.quantity()); buf.writeLong(task.startTime()); buf.writeInt(task.completionPercentage()); List elements = task.elements(); buf.writeInt(elements.size()); for (ICraftingMonitorElement element : elements) { buf.writeResourceLocation(element.getId()); element.write(buf); } } } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/craftingmonitor/WirelessCraftingMonitorSettingsUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.craftingmonitor; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.WirelessCraftingMonitor; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import java.util.Optional; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class WirelessCraftingMonitorSettingsUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_crafting_monitor_settings_update"); private final Optional tabSelected; private final int tabPage; public WirelessCraftingMonitorSettingsUpdateMessage(Optional tabSelected, int tabPage) { this.tabSelected = tabSelected; this.tabPage = tabPage; } public static WirelessCraftingMonitorSettingsUpdateMessage decode(FriendlyByteBuf buf) { Optional tabSelected = Optional.empty(); if (buf.readBoolean()) { tabSelected = Optional.of(buf.readUUID()); } int tabPage = buf.readInt(); return new WirelessCraftingMonitorSettingsUpdateMessage(tabSelected, tabPage); } public static void handle(WirelessCraftingMonitorSettingsUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof CraftingMonitorContainerMenu) { ((WirelessCraftingMonitor) ((CraftingMonitorContainerMenu) player.containerMenu).getCraftingMonitor()).setSettings( message.tabSelected, message.tabPage); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeBoolean(tabSelected.isPresent()); tabSelected.ifPresent(buf::writeUUID); buf.writeInt(tabPage); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeRequestMessage.java ================================================ package com.refinedmods.refinedstorage.network.disk; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.UUID; public class StorageDiskSizeRequestMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "storage_disk_size_request"); private final UUID id; public StorageDiskSizeRequestMessage(UUID id) { this.id = id; } public static StorageDiskSizeRequestMessage decode(FriendlyByteBuf buf) { return new StorageDiskSizeRequestMessage(buf.readUUID()); } public static void handle(StorageDiskSizeRequestMessage message, PlayPayloadContext context) { context.player().ifPresent(player -> context.workHandler().submitAsync(() -> { IStorageDisk disk = API.instance().getStorageDiskManager(((ServerPlayer) player).serverLevel()).get(message.id); if (disk != null) { RS.NETWORK_HANDLER.sendTo((ServerPlayer) player, new StorageDiskSizeResponseMessage(message.id, disk.getStored(), disk.getCapacity())); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/disk/StorageDiskSizeResponseMessage.java ================================================ package com.refinedmods.refinedstorage.network.disk; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.storage.disk.StorageDiskSyncData; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.storage.disk.StorageDiskSync; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class StorageDiskSizeResponseMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "storage_disk_size_response"); private final UUID id; private final int stored; private final int capacity; public StorageDiskSizeResponseMessage(UUID id, int stored, int capacity) { this.id = id; this.stored = stored; this.capacity = capacity; } public static StorageDiskSizeResponseMessage decode(FriendlyByteBuf buf) { return new StorageDiskSizeResponseMessage(buf.readUUID(), buf.readInt(), buf.readInt()); } public static void handle(StorageDiskSizeResponseMessage message, PlayPayloadContext context) { context.workHandler().submitAsync(() -> ((StorageDiskSync) API.instance().getStorageDiskSync()).setData( message.id, new StorageDiskSyncData(message.stored, message.capacity) )); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeInt(stored); buf.writeInt(capacity); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridClearMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridClearMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_clear"); public static void handle(GridClearMessage msg, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { ((GridContainerMenu) container).getGrid().onClear(player); } })); } @Override public void write(FriendlyByteBuf buf) { // no op } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingPreviewRequestMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridCraftingPreviewRequestMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_crafting_preview_request"); private final UUID id; private final int quantity; private final boolean noPreview; private final boolean fluids; public GridCraftingPreviewRequestMessage(UUID id, int quantity, boolean noPreview, boolean fluids) { this.id = id; this.quantity = quantity; this.noPreview = noPreview; this.fluids = fluids; } public static GridCraftingPreviewRequestMessage decode(FriendlyByteBuf buf) { return new GridCraftingPreviewRequestMessage( buf.readUUID(), buf.readInt(), buf.readBoolean(), buf.readBoolean() ); } public static void handle(GridCraftingPreviewRequestMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (message.fluids) { if (grid.getFluidHandler() != null) { grid.getFluidHandler() .onCraftingPreviewRequested((ServerPlayer) player, message.id, message.quantity, message.noPreview); } } else { if (grid.getItemHandler() != null) { grid.getItemHandler() .onCraftingPreviewRequested((ServerPlayer) player, message.id, message.quantity, message.noPreview); } } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeInt(quantity); buf.writeBoolean(noPreview); buf.writeBoolean(fluids); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingPreviewResponseMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.network.ClientProxy; import java.util.LinkedList; import java.util.List; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridCraftingPreviewResponseMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_crafting_preview_response"); private final List elements; private final UUID id; private final int quantity; private final boolean fluids; public GridCraftingPreviewResponseMessage(List elements, UUID id, int quantity, boolean fluids) { this.elements = elements; this.id = id; this.quantity = quantity; this.fluids = fluids; } public static GridCraftingPreviewResponseMessage decode(FriendlyByteBuf buf) { UUID id = buf.readUUID(); int quantity = buf.readInt(); boolean fluids = buf.readBoolean(); List elements = new LinkedList<>(); int size = buf.readInt(); for (int i = 0; i < size; i++) { ResourceLocation type = buf.readResourceLocation(); elements.add(API.instance().getCraftingPreviewElementRegistry().get(type).apply(buf)); } return new GridCraftingPreviewResponseMessage(elements, id, quantity, fluids); } public static void handle(GridCraftingPreviewResponseMessage message, PlayPayloadContext ctx) { ctx.workHandler().submitAsync(() -> ClientProxy.onReceivedCraftingPreviewResponseMessage(message)); } public List getElements() { return elements; } public UUID getId() { return id; } public int getQuantity() { return quantity; } public boolean isFluids() { return fluids; } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeInt(quantity); buf.writeBoolean(fluids); buf.writeInt(elements.size()); for (ICraftingPreviewElement element : elements) { buf.writeResourceLocation(element.getId()); element.write(buf); } } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingStartRequestMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridCraftingStartRequestMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_crafting_start_request"); private final UUID id; private final int quantity; private final boolean fluids; public GridCraftingStartRequestMessage(UUID id, int quantity, boolean fluids) { this.id = id; this.quantity = quantity; this.fluids = fluids; } public static GridCraftingStartRequestMessage decode(FriendlyByteBuf buf) { return new GridCraftingStartRequestMessage( buf.readUUID(), buf.readInt(), buf.readBoolean() ); } public static void handle(GridCraftingStartRequestMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (message.fluids) { if (grid.getFluidHandler() != null) { grid.getFluidHandler().onCraftingRequested((ServerPlayer) player, message.id, message.quantity); } } else { if (grid.getItemHandler() != null) { grid.getItemHandler().onCraftingRequested((ServerPlayer) player, message.id, message.quantity); } } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeInt(quantity); buf.writeBoolean(fluids); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridCraftingStartResponseMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.network.ClientProxy; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridCraftingStartResponseMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_crafting_start_response"); public static void handle(GridCraftingStartResponseMessage msg, PlayPayloadContext ctx) { ctx.workHandler().submitAsync(ClientProxy::onReceivedCraftingStartResponseMessage); } @Override public void write(FriendlyByteBuf buf) { // no op } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidDeltaMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.LinkedList; import java.util.List; public class GridFluidDeltaMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_fluid_delta"); private final List> deltas; public GridFluidDeltaMessage(List> deltas) { this.deltas = deltas; } public static GridFluidDeltaMessage decode(FriendlyByteBuf buf) { final int size = buf.readInt(); final List> deltas = new LinkedList<>(); for (int i = 0; i < size; ++i) { deltas.add(StackUtils.readFluidGridStackDelta(buf)); } return new GridFluidDeltaMessage(deltas); } public static void handle(GridFluidDeltaMessage message, PlayPayloadContext ctx) { BaseScreen.executeLater(GridScreen.class, grid -> { message.deltas.forEach(p -> grid.getView().postChange(p.stack(), p.change())); }); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(deltas.size()); deltas.forEach(delta -> StackUtils.writeFluidGridStackDelta(buf, delta)); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidInsertHeldMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridFluidInsertHeldMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_fluid_insert_held"); public static void handle(GridFluidInsertHeldMessage msg, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (grid.getFluidHandler() != null) { grid.getFluidHandler().onInsertHeldContainer((ServerPlayer) player); } } })); } @Override public void write(FriendlyByteBuf buf) { // no op } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidPullMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import java.util.UUID; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridFluidPullMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_fluid_pull"); private final UUID id; private final boolean shift; public GridFluidPullMessage(UUID id, boolean shift) { this.id = id; this.shift = shift; } public static GridFluidPullMessage decode(FriendlyByteBuf buf) { return new GridFluidPullMessage(buf.readUUID(), buf.readBoolean()); } public static void handle(GridFluidPullMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (grid.getFluidHandler() != null) { grid.getFluidHandler().onExtract((ServerPlayer) player, message.id, message.shift); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeBoolean(shift); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridFluidUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.ArrayList; import java.util.List; public class GridFluidUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_fluid_update"); private final boolean canCraft; private final List stacks; public GridFluidUpdateMessage(final boolean canCraft, final List stacks) { this.canCraft = canCraft; this.stacks = stacks; } public static GridFluidUpdateMessage decode(FriendlyByteBuf buf) { final boolean canCraft = buf.readBoolean(); final int size = buf.readInt(); final List stacks = new ArrayList<>(); for (int i = 0; i < size; ++i) { stacks.add(StackUtils.readFluidGridStack(buf)); } return new GridFluidUpdateMessage(canCraft, stacks); } public static void handle(GridFluidUpdateMessage message, PlayPayloadContext ctx) { BaseScreen.executeLater(GridScreen.class, grid -> { grid.setView(new GridViewImpl(grid, GridScreen.getDefaultSorter(), GridScreen.getSorters())); grid.getView().setCanCraft(message.canCraft); grid.getView().setStacks(message.stacks); grid.getView().forceSort(); }); } @Override public void write(FriendlyByteBuf buf) { buf.writeBoolean(canCraft); buf.writeInt(stacks.size()); stacks.forEach(stack -> StackUtils.writeFluidGridStack(buf, stack)); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemDeltaMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.util.StackUtils; import java.util.LinkedList; import java.util.List; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridItemDeltaMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_delta"); private final List> deltas; public GridItemDeltaMessage(List> deltas) { this.deltas = deltas; } public static GridItemDeltaMessage decode(FriendlyByteBuf buf) { final int size = buf.readInt(); final List> deltas = new LinkedList<>(); for (int i = 0; i < size; ++i) { deltas.add(StackUtils.readItemGridStackDelta(buf)); } return new GridItemDeltaMessage(deltas); } public static void handle(GridItemDeltaMessage message, PlayPayloadContext ctx) { BaseScreen.executeLater(GridScreen.class, grid -> { message.deltas.forEach(p -> grid.getView().postChange(p.stack(), p.change())); }); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(deltas.size()); deltas.forEach(delta -> StackUtils.writeItemGridStackDelta(buf, delta)); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemGridScrollMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import javax.annotation.Nullable; import java.util.UUID; public class GridItemGridScrollMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_grid_scroll"); private final UUID id; private final boolean shift; private final boolean up; public GridItemGridScrollMessage(@Nullable UUID id, boolean shift, boolean up) { this.id = id; this.shift = shift; this.up = up; } public static GridItemGridScrollMessage decode(FriendlyByteBuf buf) { return new GridItemGridScrollMessage(buf.readBoolean() ? buf.readUUID() : null, buf.readBoolean(), buf.readBoolean()); } public static void handle(GridItemGridScrollMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu && ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler() != null) { ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler().onGridScroll((ServerPlayer) player, message.id, message.shift, message.up); } })); } @Override public void write(FriendlyByteBuf buf) { boolean hasId = id != null; buf.writeBoolean(hasId); if (hasId) { buf.writeUUID(id); } buf.writeBoolean(shift); buf.writeBoolean(up); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemInsertHeldMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridItemInsertHeldMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_insert_held"); private final boolean single; public GridItemInsertHeldMessage(boolean single) { this.single = single; } public static GridItemInsertHeldMessage decode(FriendlyByteBuf buf) { return new GridItemInsertHeldMessage(buf.readBoolean()); } public static void handle(GridItemInsertHeldMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (grid.getItemHandler() != null) { grid.getItemHandler().onInsertHeldItem((ServerPlayer) player, message.single); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeBoolean(single); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemInventoryScrollMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridItemInventoryScrollMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_inventory_scroll"); private final int slot; private final boolean shift; private final boolean up; public GridItemInventoryScrollMessage(int slot, boolean shift, boolean up) { this.slot = slot; this.shift = shift; this.up = up; } public static GridItemInventoryScrollMessage decode(FriendlyByteBuf buf) { return new GridItemInventoryScrollMessage(buf.readInt(), buf.readBoolean(), buf.readBoolean()); } public static void handle(GridItemInventoryScrollMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu && ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler() != null) { ((GridContainerMenu) player.containerMenu).getGrid().getItemHandler().onInventoryScroll((ServerPlayer) player, message.slot, message.shift, message.up); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(slot); buf.writeBoolean(shift); buf.writeBoolean(up); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemPullMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.AbstractContainerMenu; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.UUID; public class GridItemPullMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_pull"); private final UUID id; private final int flags; public GridItemPullMessage(UUID id, int flags) { this.id = id; this.flags = flags; } public static GridItemPullMessage decode(FriendlyByteBuf buf) { return new GridItemPullMessage(buf.readUUID(), buf.readInt()); } public static void handle(GridItemPullMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { AbstractContainerMenu container = player.containerMenu; if (container instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) container).getGrid(); if (grid.getItemHandler() != null) { grid.getItemHandler().onExtract((ServerPlayer) player, message.id, -1, message.flags); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeUUID(id); buf.writeInt(flags); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridItemUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl; import com.refinedmods.refinedstorage.util.StackUtils; import java.util.ArrayList; import java.util.List; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridItemUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_item_update"); private final boolean canCraft; private final List stacks; public GridItemUpdateMessage(boolean canCraft, List stacks) { this.canCraft = canCraft; this.stacks = stacks; } public static GridItemUpdateMessage decode(FriendlyByteBuf buf) { final boolean canCraft = buf.readBoolean(); final int size = buf.readInt(); final List stacks = new ArrayList<>(); for (int i = 0; i < size; ++i) { stacks.add(StackUtils.readItemGridStack(buf)); } return new GridItemUpdateMessage(canCraft, stacks); } public static void handle(GridItemUpdateMessage message, PlayPayloadContext ctx) { BaseScreen.executeLater(GridScreen.class, grid -> { grid.setView(new GridViewImpl(grid, GridScreen.getDefaultSorter(), GridScreen.getSorters())); grid.getView().setCanCraft(message.canCraft); grid.getView().setStacks(message.stacks); grid.getView().forceSort(); }); } @Override public void write(FriendlyByteBuf buf) { buf.writeBoolean(canCraft); buf.writeInt(stacks.size()); stacks.forEach(stack -> StackUtils.writeItemGridStack(buf, stack)); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridPatternCreateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class GridPatternCreateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_pattern_create"); private final BlockPos pos; public GridPatternCreateMessage(BlockPos pos) { this.pos = pos; } public static GridPatternCreateMessage decode(FriendlyByteBuf buf) { return new GridPatternCreateMessage(buf.readBlockPos()); } public static void handle(GridPatternCreateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { BlockEntity blockEntity = player.getCommandSenderWorld().getBlockEntity(message.pos); if (blockEntity instanceof GridBlockEntity && ((GridBlockEntity) blockEntity).getNode().getGridType() == GridType.PATTERN) { ((GridBlockEntity) blockEntity).getNode().onCreatePattern(); } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeBlockPos(pos); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridProcessingTransferMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.inventory.fluid.FluidInventory; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.ArrayList; import java.util.Collection; import java.util.List; public class GridProcessingTransferMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_processing_transfer"); private final Collection inputs; private final Collection outputs; private final Collection fluidInputs; private final Collection fluidOutputs; public GridProcessingTransferMessage(Collection inputs, Collection outputs, Collection fluidInputs, Collection fluidOutputs) { this.inputs = inputs; this.outputs = outputs; this.fluidInputs = fluidInputs; this.fluidOutputs = fluidOutputs; } public static GridProcessingTransferMessage decode(FriendlyByteBuf buf) { int size = buf.readInt(); List inputs = new ArrayList<>(size); for (int i = 0; i < size; i++) { inputs.add(StackUtils.readItemStack(buf)); } size = buf.readInt(); List outputs = new ArrayList<>(size); for (int i = 0; i < size; i++) { outputs.add(StackUtils.readItemStack(buf)); } size = buf.readInt(); List fluidInputs = new ArrayList<>(size); for (int i = 0; i < size; i++) { fluidInputs.add(FluidStack.readFromPacket(buf)); } size = buf.readInt(); List fluidOutputs = new ArrayList<>(size); for (int i = 0; i < size; i++) { fluidOutputs.add(FluidStack.readFromPacket(buf)); } return new GridProcessingTransferMessage(inputs, outputs, fluidInputs, fluidOutputs); } public static void handle(GridProcessingTransferMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); if (grid.getGridType() == GridType.PATTERN) { BaseItemHandler handler = ((GridNetworkNode) grid).getProcessingMatrix(); FluidInventory handlerFluid = ((GridNetworkNode) grid).getProcessingMatrixFluids(); clearInputsAndOutputs(handler); clearInputsAndOutputs(handlerFluid); setInputs(handler, message.inputs, handlerFluid, message.fluidInputs); setOutputs(handler, message.outputs, handlerFluid, message.fluidOutputs); ((GridNetworkNode) grid).setProcessingPattern(true); ((GridNetworkNode) grid).markDirty(); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(inputs.size()); for (ItemStack stack : inputs) { StackUtils.writeItemStack(buf, stack); } buf.writeInt(outputs.size()); for (ItemStack stack : outputs) { StackUtils.writeItemStack(buf, stack); } buf.writeInt(fluidInputs.size()); for (FluidStack stack : fluidInputs) { stack.writeToPacket(buf); } buf.writeInt(fluidOutputs.size()); for (FluidStack stack : fluidOutputs) { stack.writeToPacket(buf); } } @Override public ResourceLocation id() { return ID; } private static void clearInputsAndOutputs(BaseItemHandler handler) { for (int i = 0; i < handler.getSlots(); ++i) { handler.setStackInSlot(i, ItemStack.EMPTY); } } private static void clearInputsAndOutputs(FluidInventory handler) { for (int i = 0; i < handler.getSlots(); ++i) { handler.setFluid(i, FluidStack.EMPTY); } } private static void setInputs(BaseItemHandler handler, Collection stacks, FluidInventory fluidHandler, Collection fluidStacks) { setSlots(handler, stacks, fluidHandler, fluidStacks, 0, handler.getSlots() / 2); } private static void setOutputs(BaseItemHandler handler, Collection stacks, FluidInventory fluidHandler, Collection fluidStacks) { setSlots(handler, stacks, fluidHandler, fluidStacks, handler.getSlots() / 2, handler.getSlots()); } private static void setSlots(BaseItemHandler handler, Collection stacks, FluidInventory fluidHandler, Collection fluidStacks, int begin, int end) { for (ItemStack stack : stacks) { handler.setStackInSlot(begin, stack); begin++; if (begin >= end) { break; } } for (FluidStack stack : fluidStacks) { fluidHandler.setFluid(begin, stack.copy()); begin++; if (begin >= end) { break; } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridStackDelta.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; public record GridStackDelta(int change, T stack) { } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/GridTransferMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; import java.util.List; public class GridTransferMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "grid_transfer"); private final ItemStack[][] recipe; public GridTransferMessage(final ItemStack[][] recipe) { this.recipe = recipe; } public static GridTransferMessage decode(FriendlyByteBuf buf) { int slots = buf.readInt(); final ItemStack[][] recipe = new ItemStack[slots][]; for (int i = 0; i < slots; i++) { int numberOfIngredients = buf.readInt(); recipe[i] = new ItemStack[numberOfIngredients]; for (int j = 0; j < numberOfIngredients; j++) { recipe[i][j] = StackUtils.readItemStack(buf); } } return new GridTransferMessage(recipe); } public static void handle(GridTransferMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); if (grid.getGridType() == GridType.CRAFTING || grid.getGridType() == GridType.PATTERN) { grid.onRecipeTransfer(player, message.recipe); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(recipe.length); for (ItemStack[] stacks : recipe) { buf.writeInt(stacks.length); for (ItemStack possibleStack : stacks) { StackUtils.writeItemStack(buf, possibleStack); } } } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/PortableGridSettingsUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class PortableGridSettingsUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "portable_grid_settings_update"); private final int viewType; private final int sortingDirection; private final int sortingType; private final int searchBoxMode; private final int size; private final int tabSelected; private final int tabPage; public PortableGridSettingsUpdateMessage(int viewType, int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) { this.viewType = viewType; this.sortingDirection = sortingDirection; this.sortingType = sortingType; this.searchBoxMode = searchBoxMode; this.size = size; this.tabSelected = tabSelected; this.tabPage = tabPage; } public static PortableGridSettingsUpdateMessage decode(FriendlyByteBuf buf) { return new PortableGridSettingsUpdateMessage( buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt() ); } public static void handle(PortableGridSettingsUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); if (grid instanceof PortableGrid) { ItemStack stack = ((PortableGrid) grid).getStack(); if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } if (IGrid.isValidViewType(message.viewType)) { stack.getTag().putInt(GridNetworkNode.NBT_VIEW_TYPE, message.viewType); } if (IGrid.isValidSortingDirection(message.sortingDirection)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection); } if (IGrid.isValidSortingType(message.sortingType)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType); } if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) { stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode); } if (IGrid.isValidSize(message.size)) { stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size); } stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected); stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(viewType); buf.writeInt(sortingDirection); buf.writeInt(sortingType); buf.writeInt(searchBoxMode); buf.writeInt(size); buf.writeInt(tabSelected); buf.writeInt(tabPage); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/WirelessFluidGridSettingsUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.blockentity.grid.WirelessFluidGrid; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class WirelessFluidGridSettingsUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_fluid_grid_settings_update"); private final int sortingDirection; private final int sortingType; private final int searchBoxMode; private final int size; private final int tabSelected; private final int tabPage; public WirelessFluidGridSettingsUpdateMessage(int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) { this.sortingDirection = sortingDirection; this.sortingType = sortingType; this.searchBoxMode = searchBoxMode; this.size = size; this.tabSelected = tabSelected; this.tabPage = tabPage; } public static WirelessFluidGridSettingsUpdateMessage decode(FriendlyByteBuf buf) { return new WirelessFluidGridSettingsUpdateMessage( buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt() ); } public static void handle(WirelessFluidGridSettingsUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); if (grid instanceof WirelessFluidGrid) { ItemStack stack = ((WirelessFluidGrid) grid).getStack(); if (IGrid.isValidSortingDirection(message.sortingDirection)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection); } if (IGrid.isValidSortingType(message.sortingType)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType); } if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) { stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode); } if (IGrid.isValidSize(message.size)) { stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size); } stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected); stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(sortingDirection); buf.writeInt(sortingType); buf.writeInt(searchBoxMode); buf.writeInt(size); buf.writeInt(tabSelected); buf.writeInt(tabPage); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/grid/WirelessGridSettingsUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.blockentity.grid.WirelessGrid; import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class WirelessGridSettingsUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "wireless_grid_settings_update"); private final int viewType; private final int sortingDirection; private final int sortingType; private final int searchBoxMode; private final int size; private final int tabSelected; private final int tabPage; public WirelessGridSettingsUpdateMessage(int viewType, int sortingDirection, int sortingType, int searchBoxMode, int size, int tabSelected, int tabPage) { this.viewType = viewType; this.sortingDirection = sortingDirection; this.sortingType = sortingType; this.searchBoxMode = searchBoxMode; this.size = size; this.tabSelected = tabSelected; this.tabPage = tabPage; } public static WirelessGridSettingsUpdateMessage decode(FriendlyByteBuf buf) { return new WirelessGridSettingsUpdateMessage( buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt(), buf.readInt() ); } public static void handle(WirelessGridSettingsUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof GridContainerMenu) { IGrid grid = ((GridContainerMenu) player.containerMenu).getGrid(); if (grid instanceof WirelessGrid) { ItemStack stack = ((WirelessGrid) grid).getStack(); if (!stack.hasTag()) { stack.setTag(new CompoundTag()); } if (IGrid.isValidViewType(message.viewType)) { stack.getTag().putInt(GridNetworkNode.NBT_VIEW_TYPE, message.viewType); } if (IGrid.isValidSortingDirection(message.sortingDirection)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_DIRECTION, message.sortingDirection); } if (IGrid.isValidSortingType(message.sortingType)) { stack.getTag().putInt(GridNetworkNode.NBT_SORTING_TYPE, message.sortingType); } if (IGrid.isValidSearchBoxMode(message.searchBoxMode)) { stack.getTag().putInt(GridNetworkNode.NBT_SEARCH_BOX_MODE, message.searchBoxMode); } if (IGrid.isValidSize(message.size)) { stack.getTag().putInt(GridNetworkNode.NBT_SIZE, message.size); } stack.getTag().putInt(GridNetworkNode.NBT_TAB_SELECTED, message.tabSelected); stack.getTag().putInt(GridNetworkNode.NBT_TAB_PAGE, message.tabPage); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeInt(viewType); buf.writeInt(sortingDirection); buf.writeInt(sortingType); buf.writeInt(searchBoxMode); buf.writeInt(size); buf.writeInt(tabSelected); buf.writeInt(tabPage); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/sync/BlockEntitySynchronizationParameterMessage.java ================================================ package com.refinedmods.refinedstorage.network.sync; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class BlockEntitySynchronizationParameterMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "sync_param"); private final BlockEntitySynchronizationParameter parameter; private final T value; private final boolean initial; public BlockEntitySynchronizationParameterMessage(BlockEntitySynchronizationParameter parameter, T value, boolean initial) { this.parameter = parameter; this.value = value; this.initial = initial; } public static BlockEntitySynchronizationParameterMessage decode(FriendlyByteBuf buf) { ResourceLocation id = buf.readResourceLocation(); boolean initial = buf.readBoolean(); BlockEntitySynchronizationParameter parameter = BlockEntitySynchronizationManager.getParameter(id); return new BlockEntitySynchronizationParameterMessage(parameter, parameter.getSerializer().read(buf), initial); } public static void handle(BlockEntitySynchronizationParameterMessage msg, PlayPayloadContext ctx) { msg.parameter.setValue(msg.initial, msg.value); } @Override public void write(FriendlyByteBuf buf) { buf.writeResourceLocation(parameter.getId()); buf.writeBoolean(initial); parameter.getSerializer().write(buf, value); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/network/sync/BlockEntitySynchronizationParameterUpdateMessage.java ================================================ package com.refinedmods.refinedstorage.network.sync; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.container.BaseContainerMenu; import java.util.function.BiConsumer; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.network.handling.PlayPayloadContext; public class BlockEntitySynchronizationParameterUpdateMessage implements CustomPacketPayload { public static final ResourceLocation ID = new ResourceLocation(RS.ID, "sync_param_update"); private final BlockEntitySynchronizationParameter parameter; private final Object value; public BlockEntitySynchronizationParameterUpdateMessage(BlockEntitySynchronizationParameter parameter, Object value) { this.parameter = parameter; this.value = value; } public static BlockEntitySynchronizationParameterUpdateMessage decode(FriendlyByteBuf buf) { ResourceLocation id = buf.readResourceLocation(); BlockEntitySynchronizationParameter parameter = BlockEntitySynchronizationManager.getParameter(id); Object value = null; if (parameter != null) { try { value = parameter.getSerializer().read(buf); } catch (Exception e) { // NO OP } } return new BlockEntitySynchronizationParameterUpdateMessage(parameter, value); } public static void handle(BlockEntitySynchronizationParameterUpdateMessage message, PlayPayloadContext ctx) { ctx.player().ifPresent(player -> ctx.workHandler().submitAsync(() -> { if (player.containerMenu instanceof BaseContainerMenu baseContainerMenu) { BiConsumer consumer = message.parameter.getValueConsumer(); if (consumer != null) { consumer.accept(baseContainerMenu.getBlockEntity(), message.value); } } })); } @Override public void write(FriendlyByteBuf buf) { buf.writeResourceLocation(parameter.getId()); parameter.getSerializer().write(buf, value); } @Override public ResourceLocation id() { return ID; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/recipe/CoverRecipe.java ================================================ package com.refinedmods.refinedstorage.recipe; import com.google.common.collect.Lists; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.item.CoverItem; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; import net.minecraft.world.level.Level; import net.neoforged.neoforge.common.Tags; import java.util.List; public class CoverRecipe extends CustomRecipe { public static RecipeSerializer SERIALIZER = new SimpleCraftingRecipeSerializer<>(CoverRecipe::new); public CoverRecipe(CraftingBookCategory category) { super(category); } public static boolean stackMatches(ItemStack first) { return CoverManager.isValidCover(first); } public static boolean matches(List list) { return list.size() == 2; } public static ItemStack getResult(List list) { if (list.size() == 2) { ItemStack first = list.get(0); ItemStack second = list.get(1); return getResult(first, second); } return ItemStack.EMPTY; } public static ItemStack getResult(ItemStack first, ItemStack second) { if (first.is(Tags.Items.NUGGETS_IRON)) { ItemStack stack = new ItemStack(RSItems.COVER.get()); CoverItem.setItem(stack, second); stack.setCount(6); return stack; } if (second.is(Tags.Items.NUGGETS_IRON)) { ItemStack stack = new ItemStack(RSItems.COVER.get()); CoverItem.setItem(stack, first); stack.setCount(6); return stack; } return ItemStack.EMPTY; } @Override public boolean matches(CraftingContainer craftingContainer, Level level) { List list = Lists.newArrayList(); int ingots = 0; for (int i = 0; i < craftingContainer.getContainerSize(); ++i) { ItemStack itemstack = craftingContainer.getItem(i); if (!itemstack.isEmpty()) { list.add(itemstack); if (itemstack.is(Tags.Items.NUGGETS_IRON)) { ++ingots; } else if (!stackMatches(itemstack)) { return false; } } } return matches(list) && ingots == 1; } @Override public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { List list = Lists.newArrayList(); int ingots = 0; for (int i = 0; i < inv.getContainerSize(); ++i) { ItemStack itemstack = inv.getItem(i); if (!itemstack.isEmpty()) { list.add(itemstack); if (itemstack.is(Tags.Items.NUGGETS_IRON)) { ++ingots; } else if (!stackMatches(itemstack)) { return ItemStack.EMPTY; } } } if (ingots > 1) { return ItemStack.EMPTY; } return getResult(list); } @Override public boolean canCraftInDimensions(int width, int height) { return width * height >= 2; } @Override public RecipeSerializer getSerializer() { return SERIALIZER; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/recipe/HollowCoverRecipe.java ================================================ package com.refinedmods.refinedstorage.recipe; import com.google.common.collect.Lists; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.item.CoverItem; import net.minecraft.core.RegistryAccess; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.crafting.SimpleCraftingRecipeSerializer; import net.minecraft.world.level.Level; import java.util.List; public class HollowCoverRecipe extends CustomRecipe { public static RecipeSerializer SERIALIZER = new SimpleCraftingRecipeSerializer<>(HollowCoverRecipe::new); public HollowCoverRecipe(CraftingBookCategory category) { super(category); } public static boolean stackMatches(ItemStack first) { return first.getItem() == RSItems.COVER.get(); } public static boolean matches(List list) { return list.size() == 1; } public static ItemStack getResult(List list) { if (list.size() == 1) { ItemStack first = list.get(0); return getResult(first); } return ItemStack.EMPTY; } public static ItemStack getResult(ItemStack first) { ItemStack stack = CoverItem.getItem(first); ItemStack result = new ItemStack(RSItems.HOLLOW_COVER.get()); CoverItem.setItem(result, stack); return result; } @Override public boolean matches(CraftingContainer craftingContainer, Level level) { List list = Lists.newArrayList(); for (int i = 0; i < craftingContainer.getContainerSize(); ++i) { ItemStack itemstack = craftingContainer.getItem(i); if (!itemstack.isEmpty()) { list.add(itemstack); if (!stackMatches(itemstack)) { return false; } } } return matches(list); } @Override public ItemStack assemble(CraftingContainer inv, RegistryAccess registryAccess) { List list = Lists.newArrayList(); for (int i = 0; i < inv.getContainerSize(); ++i) { ItemStack itemstack = inv.getItem(i); if (!itemstack.isEmpty()) { list.add(itemstack); if (!stackMatches(itemstack)) { return ItemStack.EMPTY; } } } return getResult(list); } @Override public boolean canCraftInDimensions(int width, int height) { return width * height >= 2; } @Override public RecipeSerializer getSerializer() { return SERIALIZER; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/recipe/UpgradeWithEnchantedBookRecipe.java ================================================ package com.refinedmods.refinedstorage.recipe; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.item.UpgradeItem; import java.util.Objects; import java.util.Optional; import javax.annotation.Nullable; import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.Holder; import net.minecraft.core.NonNullList; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.resources.RegistryFixedCodec; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.world.item.EnchantedBookItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.CraftingBookCategory; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.ShapedRecipe; import net.minecraft.world.item.crafting.ShapedRecipePattern; import net.minecraft.world.item.enchantment.Enchantment; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.EnchantmentInstance; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; public class UpgradeWithEnchantedBookRecipe extends ShapedRecipe { public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group( RegistryFixedCodec.create(Registries.ENCHANTMENT).fieldOf("enchantment") .forGetter(UpgradeWithEnchantedBookRecipe::getEnchantment), Codec.INT.fieldOf("level").orElse(1) .forGetter(UpgradeWithEnchantedBookRecipe::getEnchantmentLevel), RegistryFixedCodec.create(Registries.ITEM).fieldOf("result") .forGetter(UpgradeWithEnchantedBookRecipe::getResultItem) ).apply(instance, UpgradeWithEnchantedBookRecipe::new) ); private final Holder enchantment; private final int level; private final Holder resultItem; UpgradeWithEnchantedBookRecipe(final Holder enchantment, final int level, final Holder resultItem) { super("", CraftingBookCategory.MISC, new ShapedRecipePattern(3, 3, NonNullList.of( Ingredient.EMPTY, Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())), Ingredient.of(EnchantedBookItem.createForEnchantment(new EnchantmentInstance(enchantment.value(), level))), Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())), Ingredient.of(new ItemStack(Blocks.BOOKSHELF)), Ingredient.of(new ItemStack(RSItems.UPGRADE_ITEMS.get(UpgradeItem.Type.NORMAL).get())), Ingredient.of(new ItemStack(Blocks.BOOKSHELF)), Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())), Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())), Ingredient.of(new ItemStack(RSItems.QUARTZ_ENRICHED_IRON.get())) ), Optional.empty()), new ItemStack(resultItem.value())); this.enchantment = enchantment; this.level = level; this.resultItem = resultItem; } public Holder getResultItem() { return resultItem; } public Holder getEnchantment() { return enchantment; } @Nullable public ResourceLocation getEnchantmentId() { return enchantment.unwrapKey().map(ResourceKey::location).orElse(null); } public int getEnchantmentLevel() { return level; } @Override public boolean matches(final CraftingContainer craftingContainer, final Level theLevel) { if (!super.matches(craftingContainer, theLevel)) { return false; } final ListTag enchantments = EnchantedBookItem.getEnchantments(craftingContainer.getItem(1)); for (int i = 0; i < enchantments.size(); ++i) { final CompoundTag tag = enchantments.getCompound(i); final int containerLevel = EnchantmentHelper.getEnchantmentLevel(tag); final ResourceLocation containerEnchantment = EnchantmentHelper.getEnchantmentId(tag); if (Objects.equals(containerEnchantment, getEnchantmentId()) && containerLevel == level) { return true; } } return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/recipe/UpgradeWithEnchantedBookRecipeSerializer.java ================================================ package com.refinedmods.refinedstorage.recipe; import java.util.Objects; import com.mojang.serialization.Codec; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.Item; import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.world.item.enchantment.Enchantment; public class UpgradeWithEnchantedBookRecipeSerializer implements RecipeSerializer { @Override public Codec codec() { return UpgradeWithEnchantedBookRecipe.CODEC; } @Override public UpgradeWithEnchantedBookRecipe fromNetwork(final FriendlyByteBuf buf) { final Holder result = BuiltInRegistries.ITEM.getHolder(ResourceKey.create( Registries.ITEM, buf.readResourceLocation() )).orElseThrow(); final Holder enchantment = BuiltInRegistries.ENCHANTMENT.getHolder(ResourceKey.create( Registries.ENCHANTMENT, buf.readResourceLocation() )).orElseThrow(); final int level = buf.readInt(); return new UpgradeWithEnchantedBookRecipe(enchantment, level, result); } @Override public void toNetwork(final FriendlyByteBuf buf, final UpgradeWithEnchantedBookRecipe recipe) { buf.writeResourceLocation(recipe.getResultItem().unwrapKey().orElseThrow().location()); buf.writeResourceLocation(Objects.requireNonNull(recipe.getEnchantmentId())); buf.writeInt(recipe.getEnchantmentLevel()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/BakedModelOverrideRegistry.java ================================================ package com.refinedmods.refinedstorage.render; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.resources.ResourceLocation; import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; public class BakedModelOverrideRegistry { private final Map registry = new HashMap<>(); public void add(ResourceLocation id, BakedModelOverrideFactory factory) { registry.put(id, factory); } @Nullable public BakedModelOverrideFactory get(ResourceLocation id) { return registry.get(id); } public interface BakedModelOverrideFactory { BakedModel create(BakedModel base, Map registry); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/ConstantsCable.java ================================================ package com.refinedmods.refinedstorage.render; import com.refinedmods.refinedstorage.api.network.node.ICoverable; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import com.refinedmods.refinedstorage.render.collision.CollisionGroup; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.util.CollisionUtils; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; import javax.annotation.Nonnull; public class ConstantsCable { public static final CollisionGroup CORE = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 6, 10, 10, 10)); public static final CollisionGroup NORTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 0, 10, 10, 6)); public static final CollisionGroup EAST = new CollisionGroup().addItem(CollisionUtils.getBounds(10, 6, 6, 16, 10, 10)); public static final CollisionGroup SOUTH = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 6, 10, 10, 10, 16)); public static final CollisionGroup WEST = new CollisionGroup().addItem(CollisionUtils.getBounds(0, 6, 6, 6, 10, 10)); public static final CollisionGroup UP = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 10, 6, 10, 16, 10)); public static final CollisionGroup DOWN = new CollisionGroup().addItem(CollisionUtils.getBounds(6, 0, 6, 10, 6, 10)); public static final CollisionGroup HOLDER_NORTH = new CollisionGroup().addItem(getHolderBounds(Direction.NORTH)); public static final CollisionGroup HOLDER_EAST = new CollisionGroup().addItem(getHolderBounds(Direction.EAST)); public static final CollisionGroup HOLDER_SOUTH = new CollisionGroup().addItem(getHolderBounds(Direction.SOUTH)); public static final CollisionGroup HOLDER_WEST = new CollisionGroup().addItem(getHolderBounds(Direction.WEST)); public static final CollisionGroup HOLDER_UP = new CollisionGroup().addItem(getHolderBounds(Direction.UP)); public static final CollisionGroup HOLDER_DOWN = new CollisionGroup().addItem(getHolderBounds(Direction.DOWN)); @Nonnull public static AABB getCoverBounds(Direction side) { switch (side) { case DOWN: return CollisionUtils.getBounds(0, 0, 0, 16, 2, 16); case UP: return CollisionUtils.getBounds(0, 14, 0, 16, 16, 16); case NORTH: return CollisionUtils.getBounds(0, 0, 0, 16, 16, 2); case SOUTH: return CollisionUtils.getBounds(0, 0, 14, 16, 16, 16); case WEST: return CollisionUtils.getBounds(0, 0, 0, 2, 16, 16); case EAST: return CollisionUtils.getBounds(14, 0, 0, 16, 16, 16); default: return null; } } @Nonnull public static AABB getHolderBounds(Direction side) { switch (side) { case DOWN: return CollisionUtils.getBounds(7, 2, 7, 9, 6, 9); case UP: return CollisionUtils.getBounds(7, 10, 7, 9, 14, 9); case NORTH: return CollisionUtils.getBounds(7, 7, 2, 9, 9, 6); case SOUTH: return CollisionUtils.getBounds(7, 7, 10, 9, 9, 14); case WEST: return CollisionUtils.getBounds(2, 7, 7, 6, 9, 9); case EAST: return CollisionUtils.getBounds(10, 7, 7, 14, 9, 9); default: return null; } } public static VoxelShape addCoverVoxelShapes(VoxelShape shape, BlockGetter world, BlockPos pos) { if (world != null) { BlockEntity entity = world.getBlockEntity(pos); if (entity instanceof NetworkNodeBlockEntity && ((NetworkNodeBlockEntity) entity).getNode() instanceof ICoverable) { CoverManager coverManager = ((ICoverable) ((NetworkNodeBlockEntity) entity).getNode()).getCoverManager(); for (Direction value : Direction.values()) { Cover cover = coverManager.getCover(value); if (cover != null) { shape = Shapes.or(shape, Shapes.create(ConstantsCable.getCoverBounds(value))); if (cover.getType() == CoverType.NORMAL) { shape = Shapes.or(shape, Shapes.create(ConstantsCable.getHolderBounds(value))); } } } } } return shape; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/FluidRenderer.java ================================================ package com.refinedmods.refinedstorage.render; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.*; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import org.joml.Matrix4f; import javax.annotation.Nullable; /** * @see JEI implementation */ public class FluidRenderer { public static final FluidRenderer INSTANCE = new FluidRenderer(FluidType.BUCKET_VOLUME, 16, 16, 16); private static final int TEX_WIDTH = 16; private static final int TEX_HEIGHT = 16; private final int capacityMb; private final int width; private final int height; private final int minHeight; public FluidRenderer(int capacityMb, int width, int height, int minHeight) { this.capacityMb = capacityMb; this.width = width; this.height = height; this.minHeight = minHeight; } private static TextureAtlasSprite getStillFluidSprite(FluidStack fluidStack) { Minecraft minecraft = Minecraft.getInstance(); Fluid fluid = fluidStack.getFluid(); IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid); ResourceLocation fluidStill = attributes.getStillTexture(fluidStack); return minecraft.getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidStill); } private static void setGLColorFromInt(int color) { float red = (color >> 16 & 0xFF) / 255.0F; float green = (color >> 8 & 0xFF) / 255.0F; float blue = (color & 0xFF) / 255.0F; float alpha = ((color >> 24) & 0xFF) / 255F; RenderSystem.setShaderColor(red, green, blue, alpha); } private static void drawTextureWithMasking(Matrix4f matrix, float xCoord, float yCoord, TextureAtlasSprite textureSprite, int maskTop, int maskRight, float zLevel) { float uMin = textureSprite.getU0(); float uMax = textureSprite.getU1(); float vMin = textureSprite.getV0(); float vMax = textureSprite.getV1(); uMax = uMax - (maskRight / 16F * (uMax - uMin)); vMax = vMax - (maskTop / 16F * (vMax - vMin)); RenderSystem.setShader(GameRenderer::getPositionTexShader); Tesselator tessellator = Tesselator.getInstance(); BufferBuilder bufferBuilder = tessellator.getBuilder(); bufferBuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX); bufferBuilder.vertex(matrix, xCoord, yCoord + 16, zLevel).uv(uMin, vMax).endVertex(); bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + 16, zLevel).uv(uMax, vMax).endVertex(); bufferBuilder.vertex(matrix, xCoord + 16 - maskRight, yCoord + maskTop, zLevel).uv(uMax, vMin).endVertex(); bufferBuilder.vertex(matrix, xCoord, yCoord + maskTop, zLevel).uv(uMin, vMin).endVertex(); tessellator.end(); } public void render(GuiGraphics graphics, final int xPosition, final int yPosition, @Nullable FluidStack fluidStack) { RenderSystem.enableBlend(); drawFluid(graphics.pose(), xPosition, yPosition, fluidStack); RenderSystem.setShaderColor(1, 1, 1, 1); RenderSystem.disableBlend(); } private void drawFluid(PoseStack poseStack, final int xPosition, final int yPosition, @Nullable FluidStack fluidStack) { if (fluidStack == null) { return; } Fluid fluid = fluidStack.getFluid(); if (fluid == null) { return; } TextureAtlasSprite fluidStillSprite = getStillFluidSprite(fluidStack); IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid); int fluidColor = attributes.getTintColor(fluidStack); int amount = fluidStack.getAmount(); int scaledAmount = (amount * height) / capacityMb; if (amount > 0 && scaledAmount < minHeight) { scaledAmount = minHeight; } if (scaledAmount > height) { scaledAmount = height; } drawTiledSprite(poseStack, xPosition, yPosition, width, height, fluidColor, scaledAmount, fluidStillSprite); } private void drawTiledSprite(PoseStack poseStack, final int xPosition, final int yPosition, final int tiledWidth, final int tiledHeight, int color, int scaledAmount, TextureAtlasSprite sprite) { RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); Matrix4f matrix = poseStack.last().pose(); setGLColorFromInt(color); final int xTileCount = tiledWidth / TEX_WIDTH; final int xRemainder = tiledWidth - (xTileCount * TEX_WIDTH); final int yTileCount = scaledAmount / TEX_HEIGHT; final int yRemainder = scaledAmount - (yTileCount * TEX_HEIGHT); final int yStart = yPosition + tiledHeight; for (int xTile = 0; xTile <= xTileCount; xTile++) { for (int yTile = 0; yTile <= yTileCount; yTile++) { int width = (xTile == xTileCount) ? xRemainder : TEX_WIDTH; int height = (yTile == yTileCount) ? yRemainder : TEX_HEIGHT; int x = xPosition + (xTile * TEX_WIDTH); int y = yStart - ((yTile + 1) * TEX_HEIGHT); if (width > 0 && height > 0) { int maskTop = TEX_HEIGHT - height; int maskRight = TEX_WIDTH - width; drawTextureWithMasking(matrix, x, y, sprite, maskTop, maskRight, 100); } } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/RenderSettings.java ================================================ package com.refinedmods.refinedstorage.render; import net.minecraft.ChatFormatting; public class RenderSettings { public static final RenderSettings INSTANCE = new RenderSettings(); private int primaryColor; private int secondaryColor; public RenderSettings() { setColors(-1, -1); } public void setColors(int primaryColor, int secondaryColor) { if (primaryColor == -1) { this.primaryColor = 4210752; } else { this.primaryColor = primaryColor; } if (secondaryColor == -1) { this.secondaryColor = ChatFormatting.WHITE.getColor(); } else { this.secondaryColor = secondaryColor; } } public int getPrimaryColor() { return primaryColor; } public int getSecondaryColor() { return secondaryColor; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/Styles.java ================================================ package com.refinedmods.refinedstorage.render; import net.minecraft.ChatFormatting; import net.minecraft.network.chat.Style; import net.minecraft.network.chat.TextColor; public final class Styles { public static final Style WHITE = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.WHITE)); public static final Style GRAY = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.GRAY)); public static final Style YELLOW = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.YELLOW)); public static final Style RED = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.RED)); public static final Style BLUE = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.BLUE)); public static final Style AQUA = Style.EMPTY.withColor(TextColor.fromLegacyFormat(ChatFormatting.AQUA)); private Styles() { } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/blockentity/PatternItemBlockEntityRenderer.java ================================================ package com.refinedmods.refinedstorage.render.blockentity; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.item.PatternItem; import net.minecraft.client.Minecraft; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.extensions.common.IClientItemExtensions; public class PatternItemBlockEntityRenderer extends BlockEntityWithoutLevelRenderer { private static PatternItemBlockEntityRenderer instance; public PatternItemBlockEntityRenderer(BlockEntityRenderDispatcher dispatcher, EntityModelSet entityModelSet) { super(dispatcher, entityModelSet); } @Override public void renderByItem(ItemStack stack, ItemDisplayContext context, PoseStack poseStack, MultiBufferSource renderTypeBuffer, int combinedLight, int combinedOverlay) { ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack); ItemStack outputStack = pattern.getOutputs().get(0); IClientItemExtensions.of(outputStack.getItem()).getCustomRenderer() .renderByItem(outputStack, context, poseStack, renderTypeBuffer, combinedLight, combinedOverlay); } public static PatternItemBlockEntityRenderer getInstance() { if (instance == null) { instance = new PatternItemBlockEntityRenderer( Minecraft.getInstance().getBlockEntityRenderDispatcher(), Minecraft.getInstance().getEntityModels() ); } return instance; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/blockentity/StorageMonitorBlockEntityRenderer.java ================================================ package com.refinedmods.refinedstorage.render.blockentity; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.block.StorageMonitorBlock; import com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.blockentity.BlockEntityRenderer; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; import net.neoforged.neoforge.common.util.TransformationHelper; import net.neoforged.neoforge.fluids.FluidStack; import org.joml.Vector3f; public class StorageMonitorBlockEntityRenderer implements BlockEntityRenderer { @Override public void render(StorageMonitorBlockEntity blockEntity, float partialTicks, PoseStack poseStack, MultiBufferSource renderTypeBuffer, int i, int i1) { Direction direction = Direction.NORTH; BlockState state = blockEntity.getLevel().getBlockState(blockEntity.getBlockPos()); if (state.getBlock() instanceof StorageMonitorBlock) { direction = state.getValue(RSBlocks.STORAGE_MONITOR.get().getDirection().getProperty()); } final int light = LevelRenderer.getLightColor(blockEntity.getLevel(), blockEntity.getBlockPos().offset(direction.getNormal())); final float rotation = (float) (Math.PI * (360 - direction.getOpposite().get2DDataValue() * 90) / 180d); final int type = blockEntity.getStackType(); final ItemStack itemStack = blockEntity.getItemStack(); final FluidStack fluidStack = blockEntity.getFluidStack(); if (type == IType.ITEMS && itemStack != null && !itemStack.isEmpty()) { renderItem(poseStack, renderTypeBuffer, direction, rotation, light, itemStack); String amount = API.instance().getQuantityFormatter().formatWithUnits(blockEntity.getAmount()); renderText(poseStack, renderTypeBuffer, direction, rotation, light, amount); } else if (type == IType.FLUIDS && fluidStack != null && !fluidStack.isEmpty()) { renderFluid(poseStack, renderTypeBuffer, direction, rotation, light, fluidStack); String amount = API.instance().getQuantityFormatter().formatInBucketFormWithOnlyTrailingDigitsIfZero(blockEntity.getAmount()); renderText(poseStack, renderTypeBuffer, direction, rotation, light, amount); } } private void renderText(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, String amount) { poseStack.pushPose(); float stringOffset = -(Minecraft.getInstance().font.width(amount) * 0.01F) / 2F; poseStack.translate(0.5D, 0.5D, 0.5D); poseStack.translate( ((float) direction.getStepX() * 0.501F) + (direction.getStepZ() * stringOffset), -0.275, ((float) direction.getStepZ() * 0.501F) - (direction.getStepX() * stringOffset) ); poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(direction.getStepX() * 180, 0, direction.getStepZ() * 180), true)); poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false)); poseStack.scale(0.01F, 0.01F, 0.01F); Minecraft.getInstance().font.drawInBatch( amount, 0, 0, -1, false, poseStack.last().pose(), renderTypeBuffer, Font.DisplayMode.NORMAL, 0, light ); poseStack.popPose(); } private void renderItem(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, ItemStack itemStack) { poseStack.pushPose(); // Put it in the middle, outwards, and facing the correct direction poseStack.translate(0.5D, 0.5D, 0.5D); poseStack.translate((float) direction.getStepX() * 0.501F, 0, (float) direction.getStepZ() * 0.501F); poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false)); // Make it look "flat" poseStack.scale(0.5F, -0.5F, -0.00005f); // Fix rotation after making it look flat poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, 0, 180), true)); BakedModel itemModel = Minecraft.getInstance().getItemRenderer().getModel(itemStack, null, null, 0); boolean render3D = itemModel.isGui3d(); if (render3D) { Lighting.setupFor3DItems(); } else { Lighting.setupForFlatItems(); } Minecraft.getInstance().getItemRenderer().render( itemStack, ItemDisplayContext.GUI, false, poseStack, renderTypeBuffer, light, OverlayTexture.NO_OVERLAY, itemModel ); poseStack.popPose(); } private void renderFluid(PoseStack poseStack, MultiBufferSource renderTypeBuffer, Direction direction, float rotation, int light, FluidStack fluidStack) { poseStack.pushPose(); poseStack.translate(0.5D, 0.5D, 0.5D); poseStack.translate((float) direction.getStepX() * 0.51F, 0.5F, (float) direction.getStepZ() * 0.51F); poseStack.mulPose(TransformationHelper.quatFromXYZ(new Vector3f(0, rotation, 0), false)); poseStack.scale(0.5F, 0.5F, 0.5F); final Fluid fluid = fluidStack.getFluid(); final IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid); final ResourceLocation fluidStill = attributes.getStillTexture(fluidStack); final TextureAtlasSprite sprite = Minecraft.getInstance().getTextureAtlas(InventoryMenu.BLOCK_ATLAS).apply(fluidStill); final int fluidColor = attributes.getTintColor(fluidStack); final VertexConsumer buffer = renderTypeBuffer.getBuffer(RenderType.text(sprite.atlasLocation())); final int colorRed = fluidColor >> 16 & 0xFF; final int colorGreen = fluidColor >> 8 & 0xFF; final int colorBlue = fluidColor & 0xFF; final int colorAlpha = fluidColor >> 24 & 0xFF; buffer.vertex(poseStack.last().pose(), -0.5F, -0.5F, 0F) .color(colorRed, colorGreen, colorBlue, colorAlpha) .uv(sprite.getU0(), sprite.getV0()) .uv2(light) .endVertex(); buffer.vertex(poseStack.last().pose(), 0.5F, -0.5F, 0F) .color(colorRed, colorGreen, colorBlue, colorAlpha) .uv(sprite.getU1(), sprite.getV0()) .uv2(light) .endVertex(); buffer.vertex(poseStack.last().pose(), 0.5F, -1.5F, 0F) .color(colorRed, colorGreen, colorBlue, colorAlpha) .uv(sprite.getU1(), sprite.getV1()) .uv2(light) .endVertex(); buffer.vertex(poseStack.last().pose(), -0.5F, -1.5F, 0F) .color(colorRed, colorGreen, colorBlue, colorAlpha) .uv(sprite.getU0(), sprite.getV1()) .uv2(light) .endVertex(); poseStack.popPose(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/collision/CollisionGroup.java ================================================ package com.refinedmods.refinedstorage.render.collision; import net.minecraft.core.Direction; import net.minecraft.world.phys.AABB; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class CollisionGroup { private List items = new ArrayList<>(); private boolean canAccessGui; @Nullable private Direction direction; public CollisionGroup addItem(AABB item) { items.add(item); return this; } public List getItems() { return items; } public boolean canAccessGui() { return canAccessGui; } public CollisionGroup setCanAccessGui(boolean canAccessGui) { this.canAccessGui = canAccessGui; return this; } @Nullable public Direction getDirection() { return direction; } public CollisionGroup setDirection(Direction direction) { this.direction = direction; return this; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/color/PatternItemColor.java ================================================ package com.refinedmods.refinedstorage.render.color; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.render.model.baked.PatternBakedModel; import net.minecraft.client.Minecraft; import net.minecraft.client.color.item.ItemColor; import net.minecraft.world.item.ItemStack; public class PatternItemColor implements ItemColor { @Override public int getColor(ItemStack stack, int tintIndex) { ICraftingPattern pattern = PatternItem.fromCache(Minecraft.getInstance().level, stack); if (PatternBakedModel.canDisplayOutput(stack, pattern)) { int color = Minecraft.getInstance().getItemColors().getColor(pattern.getOutputs().get(0), tintIndex); if (color != -1) { return color; } } return 0xFFFFFF; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/CubeBuilder.java ================================================ package com.refinedmods.refinedstorage.render.model; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.core.Direction; import net.neoforged.neoforge.client.model.pipeline.QuadBakingVertexConsumer; import org.joml.Vector3f; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; public class CubeBuilder { private Vector3f from; private Vector3f to; private final Map faces = new HashMap<>(); private int color = 0xFFFFFFFF; public CubeBuilder from(float x, float y, float z) { this.from = new Vector3f(x / 16, y / 16, z / 16); return this; } public CubeBuilder to(float x, float y, float z) { this.to = new Vector3f(x / 16, y / 16, z / 16); return this; } public CubeBuilder color(int color) { this.color = color; return this; } public CubeBuilder addFaces(Function faceSupplier) { for (Direction facing : Direction.values()) { addFace(faceSupplier.apply(facing)); } return this; } public CubeBuilder addFace(Face face) { faces.put(face.face, face); return this; } public List bake() { List quads = new ArrayList<>(); for (Map.Entry entry : faces.entrySet()) { quads.add(bakeFace(entry.getKey(), entry.getValue())); } return quads; } private BakedQuad bakeFace(Direction facing, Face cubeFace) { List quad = new ArrayList<>(); QuadBakingVertexConsumer builder = new QuadBakingVertexConsumer(quad::add); builder.setSprite(cubeFace.sprite); builder.setDirection(facing); builder.setTintIndex(-1); builder.setShade(true); Uv uv = getDefaultUv(facing, cubeFace.sprite, from.x(), from.y(), from.z(), to.x(), to.y(), to.z()); switch (facing) { case DOWN: addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv); addVertexBottomRight(builder, cubeFace, to.x(), from.y(), to.z(), uv); addVertexBottomLeft(builder, cubeFace, from.x(), from.y(), to.z(), uv); addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv); break; case UP: addVertexTopLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv); addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), to.z(), uv); addVertexBottomRight(builder, cubeFace, to.x(), to.y(), to.z(), uv); addVertexTopRight(builder, cubeFace, to.x(), to.y(), from.z(), uv); break; case NORTH: addVertexBottomRight(builder, cubeFace, to.x(), to.y(), from.z(), uv); addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv); addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv); addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv); break; case SOUTH: addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), to.z(), uv); addVertexTopLeft(builder, cubeFace, from.x(), from.y(), to.z(), uv); addVertexTopRight(builder, cubeFace, to.x(), from.y(), to.z(), uv); addVertexBottomRight(builder, cubeFace, to.x(), to.y(), to.z(), uv); break; case WEST: addVertexTopLeft(builder, cubeFace, from.x(), from.y(), from.z(), uv); addVertexTopRight(builder, cubeFace, from.x(), from.y(), to.z(), uv); addVertexBottomRight(builder, cubeFace, from.x(), to.y(), to.z(), uv); addVertexBottomLeft(builder, cubeFace, from.x(), to.y(), from.z(), uv); break; case EAST: addVertexBottomRight(builder, cubeFace, to.x(), to.y(), from.z(), uv); addVertexBottomLeft(builder, cubeFace, to.x(), to.y(), to.z(), uv); addVertexTopLeft(builder, cubeFace, to.x(), from.y(), to.z(), uv); addVertexTopRight(builder, cubeFace, to.x(), from.y(), from.z(), uv); break; } return quad.get(0); } private Uv getDefaultUv(Direction face, TextureAtlasSprite texture, float x1, float y1, float z1, float x2, float y2, float z2) { Uv uv = new Uv(); if (face.getAxis() != Direction.Axis.Y) { uv.v1 = texture.getV(1 - y1); uv.v2 = texture.getV(1 - y2); } else { uv.v1 = texture.getV(z1); uv.v2 = texture.getV(z2); } switch (face) { case DOWN, UP, SOUTH -> { uv.u1 = texture.getU(x1); uv.u2 = texture.getU(x2); } case NORTH -> { uv.u1 = texture.getU(1 - x2); uv.u2 = texture.getU(1 - x1); } case WEST -> { uv.u1 = texture.getU(z1); uv.u2 = texture.getU(z2); } case EAST -> { uv.u1 = texture.getU(1 - z2); uv.u2 = texture.getU(1 - z1); } } return uv; } private void addVertexTopLeft(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) { float u; float v; switch (face.uvRotation) { default: case CLOCKWISE_0: u = uv.u1; v = uv.v1; break; case CLOCKWISE_90: u = uv.u1; v = uv.v2; break; case CLOCKWISE_180: u = uv.u2; v = uv.v2; break; case CLOCKWISE_270: u = uv.u2; v = uv.v1; break; } addVertex(builder, face, x, y, z, u, v); } private void addVertexTopRight(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) { float u; float v; switch (face.uvRotation) { default: case CLOCKWISE_0: u = uv.u2; v = uv.v1; break; case CLOCKWISE_90: u = uv.u1; v = uv.v1; break; case CLOCKWISE_180: u = uv.u1; v = uv.v2; break; case CLOCKWISE_270: u = uv.u2; v = uv.v2; break; } addVertex(builder, face, x, y, z, u, v); } private void addVertexBottomRight(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) { float u; float v; switch (face.uvRotation) { default: case CLOCKWISE_0: u = uv.u2; v = uv.v2; break; case CLOCKWISE_90: u = uv.u2; v = uv.v1; break; case CLOCKWISE_180: u = uv.u1; v = uv.v1; break; case CLOCKWISE_270: u = uv.u1; v = uv.v2; break; } addVertex(builder, face, x, y, z, u, v); } private void addVertexBottomLeft(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, Uv uv) { float u; float v; switch (face.uvRotation) { default: case CLOCKWISE_0: u = uv.u1; v = uv.v2; break; case CLOCKWISE_90: u = uv.u2; v = uv.v2; break; case CLOCKWISE_180: u = uv.u2; v = uv.v1; break; case CLOCKWISE_270: u = uv.u1; v = uv.v1; break; } addVertex(builder, face, x, y, z, u, v); } private void addVertex(QuadBakingVertexConsumer builder, Face face, float x, float y, float z, float u, float v) { builder.vertex(x, y, z); builder.normal(face.face.getStepX(), face.face.getStepY(), face.face.getStepZ()); float r = (color >> 16 & 0xFF) / 255F; float g = (color >> 8 & 0xFF) / 255F; float b = (color & 0xFF) / 255F; float a = (color >> 24 & 0xFF) / 255F; builder.uv(u, v); builder.color(r, g, b, a); builder.endVertex(); } public enum UvRotation { CLOCKWISE_0, CLOCKWISE_90, CLOCKWISE_180, CLOCKWISE_270 } private static class Uv { private float u1; private float u2; private float v1; private float v2; } public static class Face { private final Direction face; private final TextureAtlasSprite sprite; private final UvRotation uvRotation = UvRotation.CLOCKWISE_0; public Face(Direction face, TextureAtlasSprite sprite) { this.face = face; this.sprite = sprite; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/DiskDriveGeometryLoader.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import net.neoforged.neoforge.client.model.geometry.IGeometryLoader; public class DiskDriveGeometryLoader implements IGeometryLoader { @Override public DiskDriveUnbakedGeometry read(final JsonObject jsonObject, final JsonDeserializationContext deserializationContext) { return new DiskDriveUnbakedGeometry(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/DiskDriveUnbakedGeometry.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.mojang.math.Transformation; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.render.model.baked.DiskDriveBakedModel; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.client.model.SimpleModelState; import net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext; import net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry; import org.joml.Vector3f; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; public class DiskDriveUnbakedGeometry implements IUnbakedGeometry { private static final ResourceLocation BASE_MODEL = new ResourceLocation(RS.ID, "block/disk_drive_base"); private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, "block/disks/disk"); private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_disconnected"); private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_full"); private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_near_capacity"); @Override public void resolveParents(final Function modelGetter, final IGeometryBakingContext context) { modelGetter.apply(BASE_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter); } @Override public BakedModel bake(final IGeometryBakingContext context, final ModelBaker baker, final Function spriteGetter, final ModelState modelState, final ItemOverrides overrides, final ResourceLocation modelLocation) { return new DiskDriveBakedModel( Objects.requireNonNull(baker.bake(BASE_MODEL, modelState, spriteGetter)), getBaseModelBaker(modelState, baker, spriteGetter), getDiskModelBaker(DISK_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter) ); } private Function getBaseModelBaker(final ModelState state, final ModelBaker baker, final Function sg) { return direction -> { final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked()); return baker.bake(BASE_MODEL, wrappedState, sg); }; } private BiFunction getDiskModelBaker(final ResourceLocation id, final ModelState state, final ModelBaker baker, final Function sg) { return (direction, trans) -> { final Transformation translation = new Transformation(trans, null, null, null); final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation.compose(translation), state.isUvLocked()); return baker.bake(id, wrappedState, sg); }; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/DiskManipulatorGeometryLoader.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import net.neoforged.neoforge.client.model.geometry.IGeometryLoader; public class DiskManipulatorGeometryLoader implements IGeometryLoader { @Override public DiskManipulatorUnbakedGeometry read(final JsonObject jsonObject, final JsonDeserializationContext deserializationContext) { return new DiskManipulatorUnbakedGeometry(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/DiskManipulatorUnbakedGeometry.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.mojang.math.Transformation; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.render.model.baked.DiskManipulatorBakedModel; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.DyeColor; import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.SimpleModelState; import net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext; import net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry; import org.joml.Vector3f; import java.util.HashMap; import java.util.Map; import java.util.Objects; import java.util.function.BiFunction; import java.util.function.Function; public class DiskManipulatorUnbakedGeometry implements IUnbakedGeometry { private static final ResourceLocation BASE_MODEL_DISCONNECTED = new ResourceLocation(RS.ID, "block/disk_manipulator/disconnected"); private final Map BASE_MODEL_CONNECTED = new HashMap<>(); private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, "block/disks/disk"); private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_disconnected"); private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_full"); private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, "block/disks/disk_near_capacity"); public DiskManipulatorUnbakedGeometry() { for (DyeColor value : DyeColor.values()) { BASE_MODEL_CONNECTED.put(value, new ResourceLocation(RS.ID, "block/disk_manipulator/" + value.getName())); } } @Override public void resolveParents(final Function modelGetter, final IGeometryBakingContext context) { modelGetter.apply(BASE_MODEL_DISCONNECTED).resolveParents(modelGetter); modelGetter.apply(DISK_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter); BASE_MODEL_CONNECTED.values().forEach(m -> modelGetter.apply(m).resolveParents(modelGetter)); } @Override public BakedModel bake(final IGeometryBakingContext context, final ModelBaker baker, final Function spriteGetter, final ModelState modelState, final ItemOverrides overrides, final ResourceLocation modelLocation) { var renderTypeHint = context.getRenderTypeHint(); var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY; return new DiskManipulatorBakedModel( Objects.requireNonNull(baker.bake(BASE_MODEL_DISCONNECTED, modelState, spriteGetter)), getBaseModelBakerConnected(modelState, baker, spriteGetter), getBaseModelBaker(modelState, baker, spriteGetter), getDiskModelBaker(DISK_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter), getDiskModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter), renderTypes ); } private Function getBaseModelBaker(final ModelState state, final ModelBaker baker, final Function sg) { return direction -> { final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked()); return baker.bake(BASE_MODEL_DISCONNECTED, wrappedState, sg); }; } private BiFunction getBaseModelBakerConnected(final ModelState state, final ModelBaker baker, final Function sg) { return (direction, color) -> { final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked()); return baker.bake(BASE_MODEL_CONNECTED.get(color), wrappedState, sg); }; } private BiFunction getDiskModelBaker(final ResourceLocation id, final ModelState state, final ModelBaker baker, final Function sg) { return (direction, trans) -> { final Transformation translation = new Transformation(trans, null, null, null); final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation.compose(translation), state.isUvLocked()); return baker.bake(id, wrappedState, sg); }; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/PortableGridGeometryLoader.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonObject; import net.neoforged.neoforge.client.model.geometry.IGeometryLoader; public class PortableGridGeometryLoader implements IGeometryLoader { @Override public PortableGridUnbakedGeometry read(final JsonObject jsonObject, final JsonDeserializationContext deserializationContext) { return new PortableGridUnbakedGeometry(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/PortableGridUnbakedGeometry.java ================================================ package com.refinedmods.refinedstorage.render.model; import com.mojang.math.Transformation; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.render.model.baked.PortableGridBakedModel; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.*; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.SimpleModelState; import net.neoforged.neoforge.client.model.geometry.IGeometryBakingContext; import net.neoforged.neoforge.client.model.geometry.IUnbakedGeometry; import java.util.Objects; import java.util.function.Function; public class PortableGridUnbakedGeometry implements IUnbakedGeometry { private static final ResourceLocation BASE_CONNECTED_MODEL = new ResourceLocation(RS.ID, "block/portable_grid_connected"); private static final ResourceLocation BASE_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, "block/portable_grid_disconnected"); private static final ResourceLocation DISK_MODEL = new ResourceLocation(RS.ID, "block/disks/portable_grid_disk"); private static final ResourceLocation DISK_DISCONNECTED_MODEL = new ResourceLocation(RS.ID, "block/disks/portable_grid_disk_disconnected"); private static final ResourceLocation DISK_FULL_MODEL = new ResourceLocation(RS.ID, "block/disks/portable_grid_disk_full"); private static final ResourceLocation DISK_NEAR_CAPACITY_MODEL = new ResourceLocation(RS.ID, "block/disks/portable_grid_disk_near_capacity"); @Override public void resolveParents(final Function modelGetter, final IGeometryBakingContext context) { modelGetter.apply(BASE_CONNECTED_MODEL).resolveParents(modelGetter); modelGetter.apply(BASE_DISCONNECTED_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_DISCONNECTED_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_FULL_MODEL).resolveParents(modelGetter); modelGetter.apply(DISK_NEAR_CAPACITY_MODEL).resolveParents(modelGetter); } @Override public BakedModel bake(final IGeometryBakingContext context, final ModelBaker baker, final Function spriteGetter, final ModelState modelState, final ItemOverrides overrides, final ResourceLocation modelLocation) { var renderTypeHint = context.getRenderTypeHint(); var renderTypes = renderTypeHint != null ? context.getRenderType(renderTypeHint) : RenderTypeGroup.EMPTY; return new PortableGridBakedModel( Objects.requireNonNull(baker.bake(BASE_CONNECTED_MODEL, modelState, spriteGetter)), getModelBaker(BASE_CONNECTED_MODEL, modelState, baker, spriteGetter), getModelBaker(BASE_DISCONNECTED_MODEL, modelState, baker, spriteGetter), getModelBaker(DISK_MODEL, modelState, baker, spriteGetter), getModelBaker(DISK_NEAR_CAPACITY_MODEL, modelState, baker, spriteGetter), getModelBaker(DISK_FULL_MODEL, modelState, baker, spriteGetter), getModelBaker(DISK_DISCONNECTED_MODEL, modelState, baker, spriteGetter), renderTypes ); } private Function getModelBaker(final ResourceLocation id, final ModelState state, final ModelBaker baker, final Function sg) { return direction -> { final Transformation rotation = new Transformation(null, RenderUtils.getQuaternion(direction), null, null); final ModelState wrappedState = new SimpleModelState(rotation, state.isUvLocked()); return baker.bake(id, wrappedState, sg); }; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/CableCoverBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverManager; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.render.ConstantsCable; import com.refinedmods.refinedstorage.render.model.CubeBuilder; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; import net.neoforged.neoforge.client.model.BakedModelWrapper; import net.neoforged.neoforge.client.model.data.ModelData; import org.joml.Vector3f; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; public class CableCoverBakedModel extends BakedModelWrapper { private static TextureAtlasSprite BORDER_SPRITE; public CableCoverBakedModel(BakedModel base) { super(base); } private static int getHollowCoverSize(@Nullable BlockState state, Direction coverSide) { if (state == null) { return 6; } BaseBlock block = (BaseBlock) state.getBlock(); if (block == RSBlocks.CABLE.get()) { return 6; } if (block.getDirection() != null && state.getValue(block.getDirection().getProperty()) == coverSide) { if (block == RSBlocks.EXPORTER.get()) { return 6; } else if (block == RSBlocks.EXTERNAL_STORAGE.get() || block == RSBlocks.IMPORTER.get()) { return 3; } else if (block == RSBlocks.CONSTRUCTOR.get() || block == RSBlocks.DESTRUCTOR.get()) { //Removed reader and writer return 2; } } return 6; } protected static void addCover(List quads, @Nullable Cover cover, Direction coverSide, Direction side, RandomSource rand, @Nullable CoverManager manager, BlockState state, boolean handle) { if (cover == null) { return; } BlockState coverState = CoverManager.getBlockState(cover.getStack()); if (coverState == null) { return; } boolean hasUp = false, hasDown = false, hasEast = false, hasWest = false; if (manager != null) { hasUp = manager.hasCover(Direction.UP); hasDown = manager.hasCover(Direction.DOWN); hasEast = manager.hasCover(Direction.EAST); hasWest = manager.hasCover(Direction.WEST); } switch (cover.getType()) { case NORMAL -> addNormalCover(quads, coverState, coverSide, hasUp, hasDown, hasEast, hasWest, handle, rand); case HOLLOW -> addHollowCover(quads, coverState, coverSide, hasUp, hasDown, hasEast, hasWest, getHollowCoverSize(state, coverSide), rand); } } private static void addNormalCover(List quads, BlockState state, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, boolean handle, RandomSource random) { AABB bounds = ConstantsCable.getCoverBounds(coverSide); float fromX = (float) bounds.minX * 16; float fromY = (float) bounds.minY * 16; float fromZ = (float) bounds.minZ * 16; float toX = (float) bounds.maxX * 16; float toY = (float) bounds.maxY * 16; float toZ = (float) bounds.maxZ * 16; if (coverSide == Direction.NORTH) { if (hasWest) { fromX = 2; } if (hasEast) { toX = 14; } } else if (coverSide == Direction.SOUTH) { if (hasWest) { fromX = 2; } if (hasEast) { toX = 14; } } if (coverSide.getAxis() != Direction.Axis.Y) { if (hasDown) { fromY = 2; } if (hasUp) { toY = 14; } } Vector3f from = new Vector3f(fromX, fromY, fromZ); Vector3f to = new Vector3f(toX, toY, toZ); HashMap spriteCache = new HashMap<>(); //Changed from 1.12: to improve sprite getting for each side 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()); if (handle) { if (BORDER_SPRITE == null) { BORDER_SPRITE = Minecraft.getInstance().getTextureAtlas(TextureAtlas.LOCATION_BLOCKS).apply(new ResourceLocation(RS.ID, "block/cable_part_border")); } bounds = ConstantsCable.getHolderBounds(coverSide); from = new Vector3f((float) bounds.minX * 16, (float) bounds.minY * 16, (float) bounds.minZ * 16); to = new Vector3f((float) bounds.maxX * 16, (float) bounds.maxY * 16, (float) bounds.maxZ * 16); 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()); } } private static void addHollowCover(List quads, BlockState state, Direction coverSide, boolean hasUp, boolean hasDown, boolean hasEast, boolean hasWest, int size, RandomSource random) { AABB bounds = ConstantsCable.getCoverBounds(coverSide); float fromX = (float) bounds.minX * 16; float fromY = (float) bounds.minY * 16; float fromZ = (float) bounds.minZ * 16; float toX = (float) bounds.maxX * 16; float toY = (float) bounds.maxY * 16; float toZ = (float) bounds.maxZ * 16; if (coverSide.getAxis() != Direction.Axis.Y) { if (hasDown) { fromY = 2; } if (hasUp) { toY = 14; } } // Right if (coverSide == Direction.NORTH) { if (hasWest) { fromX = 2; } else { fromX = 0; } toX = size; } else if (coverSide == Direction.SOUTH) { if (hasEast) { toX = 14; } else { toX = 16; } fromX = 16F - size; } else if (coverSide == Direction.EAST) { fromZ = 0; toZ = size; } else if (coverSide == Direction.WEST) { fromZ = 16F - size; toZ = 16; } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) { fromZ = 16F - size; toZ = 16; } HashMap spriteCache = new HashMap<>(); //Changed from 1.12: to improve sprite getting for each side quads.addAll(new CubeBuilder() .from(fromX, fromY, fromZ) .to(toX, toY, toZ) .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random)))) .bake() ); // Left if (coverSide == Direction.NORTH) { if (hasEast) { toX = 14; } else { toX = 16; } fromX = 16F - size; } else if (coverSide == Direction.SOUTH) { if (hasWest) { fromX = 2; } else { fromX = 0; } toX = size; } else if (coverSide == Direction.EAST) { fromZ = 16F - size; toZ = 16; } else if (coverSide == Direction.WEST) { fromZ = 0; toZ = size; } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) { fromZ = 0; toZ = size; } quads.addAll(new CubeBuilder() .from(fromX, fromY, fromZ) .to(toX, toY, toZ) .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random)))) .bake() ); // Bottom if (coverSide == Direction.NORTH) { fromX = size; toX = 16F - size; if (hasDown) { fromY = 2; } else { fromY = 0; } toY = size; } else if (coverSide == Direction.SOUTH) { fromX = size; toX = 16F - size; if (hasDown) { fromY = 2; } else { fromY = 0; } toY = size; } else if (coverSide == Direction.EAST) { fromZ = size; toZ = 16F - size; if (hasDown) { fromY = 2; } else { fromY = 0; } toY = size; } else if (coverSide == Direction.WEST) { fromZ = size; toZ = 16F - size; if (hasDown) { fromY = 2; } else { fromY = 0; } toY = size; } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) { fromZ = size; toZ = 16F - size; fromX = 0; toX = size; } quads.addAll(new CubeBuilder() .from(fromX, fromY, fromZ) .to(toX, toY, toZ) .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random)))) .bake() ); // Up if (coverSide == Direction.NORTH) { fromX = size; toX = 16F - size; if (hasUp) { toY = 14; } else { toY = 16; } fromY = 16F - size; } else if (coverSide == Direction.SOUTH) { fromX = size; toX = 16F - size; if (hasUp) { toY = 14; } else { toY = 16; } fromY = 16F - size; } else if (coverSide == Direction.EAST) { fromZ = size; toZ = 16F - size; if (hasUp) { toY = 14; } else { toY = 16; } fromY = 16F - size; } else if (coverSide == Direction.WEST) { fromZ = size; toZ = 16F - size; if (hasUp) { toY = 14; } else { toY = 16; } fromY = 16F - size; } else if (coverSide == Direction.DOWN || coverSide == Direction.UP) { fromZ = size; toZ = 16F - size; fromX = 16F - size; toX = 16; } quads.addAll(new CubeBuilder() .from(fromX, fromY, fromZ) .to(toX, toY, toZ) .addFaces(face -> new CubeBuilder.Face(face, spriteCache.computeIfAbsent(face, direction -> RenderUtils.getSprite(Minecraft.getInstance().getBlockRenderer().getBlockModel(state), state, direction, random)))) .bake() ); } @Override public List getQuads(@Nullable final BlockState state, @Nullable final Direction side, @Nonnull final RandomSource rand, @Nonnull final ModelData extraData, @Nullable final RenderType renderType) { List quads = new ArrayList<>(super.getQuads(state, side, rand, extraData, renderType)); if (extraData.has(CoverManager.PROPERTY)) { CoverManager manager = extraData.get(CoverManager.PROPERTY); addCover(quads, manager.getCover(Direction.NORTH), Direction.NORTH, side, rand, manager, state, true); addCover(quads, manager.getCover(Direction.SOUTH), Direction.SOUTH, side, rand, manager, state, true); addCover(quads, manager.getCover(Direction.EAST), Direction.EAST, side, rand, manager, state, true); addCover(quads, manager.getCover(Direction.WEST), Direction.WEST, side, rand, manager, state, true); addCover(quads, manager.getCover(Direction.DOWN), Direction.DOWN, side, rand, manager, state, true); addCover(quads, manager.getCover(Direction.UP), Direction.UP, side, rand, manager, state, true); } return quads; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/CableCoverItemBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.Cover; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import com.refinedmods.refinedstorage.item.CoverItem; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Objects; import static com.refinedmods.refinedstorage.render.model.baked.CableCoverBakedModel.addCover; public class CableCoverItemBakedModel implements BakedModel { private static final LoadingCache> CACHE = CacheBuilder.newBuilder().build(new CacheLoader>() { @Override public List load(CacheKey key) { List quads = new ArrayList<>(); addCover(quads, new Cover(key.stack, key.type), Direction.NORTH, key.side, key.random, null, null, true); return quads; } }); private final ItemStack stack; private final CoverType type; public CableCoverItemBakedModel(ItemStack stack, CoverType type) { this.stack = stack; this.type = type; } @Override public List getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand) { if (stack.isEmpty()) { return Collections.emptyList(); } CacheKey key = new CacheKey(state, CoverItem.getItem(stack), side, type, rand); return CACHE.getUnchecked(key); } @Override public ItemOverrides getOverrides() { return new ItemOverrides() { @Override public BakedModel resolve(BakedModel originalModel, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { return new CableCoverItemBakedModel(stack, type); } }; } @Override public List getRenderPasses(final ItemStack itemStack, final boolean fabulous) { return List.of(this); } @Override public boolean useAmbientOcclusion() { return true; } @Override public boolean isGui3d() { return true; } @Override public boolean isCustomRenderer() { return false; } @Override public TextureAtlasSprite getParticleIcon() { return null; } @Override public boolean useAmbientOcclusion(BlockState state) { return true; } @Override @SuppressWarnings("deprecation") public ItemTransforms getTransforms() { return RenderUtils.getDefaultBlockTransforms(); } @Override public boolean usesBlockLight() { return true; } private static class CacheKey { private final BlockState state; private final ItemStack stack; private final Direction side; private final CoverType type; private final RandomSource random; CacheKey(BlockState state, ItemStack stack, Direction side, CoverType type, RandomSource rand) { this.state = state; this.stack = stack; this.side = side; this.type = type; this.random = rand; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CableCoverItemBakedModel.CacheKey cacheKey = (CableCoverItemBakedModel.CacheKey) o; return cacheKey.type == type && cacheKey.stack.getItem() == stack.getItem() && cacheKey.side == side && Objects.equals(cacheKey.state, state); } @Override public int hashCode() { int result = stack.getItem().hashCode(); result = 31 * result + (side != null ? side.hashCode() : 0); result = 31 * result + (state != null ? state.hashCode() : 0); result = 31 * result + type.hashCode(); return result; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/DiskDriveBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.BakedModelWrapper; import net.neoforged.neoforge.client.model.data.ModelData; import org.joml.Vector3f; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; public class DiskDriveBakedModel extends BakedModelWrapper { private final Function baseModelBakery; private final BiFunction diskModelBakery; private final BiFunction diskNearCapacityModelBakery; private final BiFunction diskFullModelBakery; private final BiFunction diskDisconnectedModelBakery; private final LoadingCache> cache = CacheBuilder.newBuilder().build(new CacheLoader>() { @Override @SuppressWarnings("deprecation") public List load(CacheKey key) { Direction facing = key.state.getValue(RSBlocks.DISK_DRIVE.get().getDirection().getProperty()); List quads = new ArrayList<>(); if (key.side != null) { quads = baseModelBakery.apply(facing).getQuads(key.state, key.side, key.random); return quads; } int x = 0; int y = 0; for (int i = 0; i < 8; ++i) { if (key.diskState[i] != DiskState.NONE) { BakedModel diskModel = getDiskModelBakery(key.diskState[i]).apply(facing, getDiskTranslation(x, y)); quads.addAll(diskModel.getQuads(key.state, key.side, key.random)); } x++; if ((i + 1) % 2 == 0) { y++; x = 0; } } return quads; } private BiFunction getDiskModelBakery(DiskState diskState) { return switch (diskState) { case DISCONNECTED -> diskDisconnectedModelBakery; case NEAR_CAPACITY -> diskNearCapacityModelBakery; case FULL -> diskFullModelBakery; default -> diskModelBakery; }; } private Vector3f getDiskTranslation(int x, int y) { Vector3f translation = new Vector3f(); translation.add(((2F / 16F) + ((float) x * 7F) / 16F) * -1, 0, 0); // Add to X translation.add(0, -((2F / 16F) + ((float) y * 3F) / 16F), 0); // Remove from Y return translation; } }); public DiskDriveBakedModel(BakedModel base, Function baseModelBakery, BiFunction diskModelBakery, BiFunction diskNearCapacityModelBakery, BiFunction diskFullModelBakery, BiFunction diskDisconnectedModelBakery) { super(base); this.baseModelBakery = baseModelBakery; this.diskModelBakery = diskModelBakery; this.diskNearCapacityModelBakery = diskNearCapacityModelBakery; this.diskFullModelBakery = diskFullModelBakery; this.diskDisconnectedModelBakery = diskDisconnectedModelBakery; } @Nonnull @Override public List getQuads(@Nullable final BlockState state, @Nullable final Direction side, @Nonnull final RandomSource rand, @Nonnull final ModelData extraData, @Nullable final RenderType renderType) { DiskState[] diskState = extraData.get(DiskDriveBlockEntity.DISK_STATE_PROPERTY); if (diskState == null) { return super.getQuads(state, side, rand, extraData, renderType); } CacheKey key = new CacheKey(state, side, diskState, rand); return cache.getUnchecked(key); } private static class CacheKey { private final BlockState state; private final Direction side; private final DiskState[] diskState; private final RandomSource random; CacheKey(BlockState state, @Nullable Direction side, DiskState[] diskState, RandomSource random) { this.state = state; this.side = side; this.diskState = diskState; this.random = random; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CacheKey cacheKey = (CacheKey) o; if (!state.equals(cacheKey.state)) { return false; } if (side != cacheKey.side) { return false; } return Arrays.equals(diskState, cacheKey.diskState); } @Override public int hashCode() { int result = state.hashCode(); result = 31 * result + (side != null ? side.hashCode() : 0); result = 31 * result + Arrays.hashCode(diskState); return result; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/DiskManipulatorBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.apiimpl.network.node.DiskState; import com.refinedmods.refinedstorage.block.DiskManipulatorBlock; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.item.DyeColor; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.ChunkRenderTypeSet; import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.BakedModelWrapper; import net.neoforged.neoforge.client.model.data.ModelData; import org.joml.Vector3f; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.function.Function; public class DiskManipulatorBakedModel extends BakedModelWrapper { private final BiFunction baseConnectedModelBakery; private final Function baseDisconnectedModelBakery; private final BiFunction diskModelBakery; private final BiFunction diskNearCapacityModelBakery; private final BiFunction diskFullModelBakery; private final BiFunction diskDisconnectedModelBakery; private final RenderTypeGroup renderType; private final LoadingCache> cache = CacheBuilder.newBuilder().build(new CacheLoader>() { @Override @SuppressWarnings("deprecation") public List load(CacheKey key) { Direction facing = key.state.getValue(RSBlocks.DISK_MANIPULATOR.get(ColorMap.DEFAULT_COLOR).get().getDirection().getProperty()); boolean connected = key.state.getValue(NetworkNodeBlock.CONNECTED); List quads; if (connected) { quads = new ArrayList<>(baseConnectedModelBakery.apply(facing, key.color).getQuads(key.state, key.side, key.random)); } else { quads = new ArrayList<>(baseDisconnectedModelBakery.apply(facing).getQuads(key.state, key.side, key.random)); } int x = 0; int y = 0; for (int i = 0; i < 6; ++i) { if (key.diskState[i] != DiskState.NONE) { BakedModel diskModel = getDiskModelBakery(key.diskState[i]).apply(facing, getDiskTranslation(facing, x, y)); quads.addAll(diskModel.getQuads(key.state, key.side, key.random)); } y++; if ((i + 1) % 3 == 0) { x++; y = 0; } } return quads; } private BiFunction getDiskModelBakery(DiskState diskState) { return switch (diskState) { case DISCONNECTED -> diskDisconnectedModelBakery; case NEAR_CAPACITY -> diskNearCapacityModelBakery; case FULL -> diskFullModelBakery; default -> diskModelBakery; }; } private Vector3f getDiskTranslation(Direction facing, int x, int y) { Vector3f translation = new Vector3f(); translation.add((2F / 16F + ((float) x * 7F) / 16F) * -1, 0, 0); // Add to X translation.add(0, -((6F / 16F) + (3F * y) / 16F), 0); // Remove from Y return translation; } }); public DiskManipulatorBakedModel(BakedModel originalModel, BiFunction baseConnectedModelBakery, Function baseDisconnectedModelBakery, BiFunction diskModelBakery, BiFunction diskNearCapacityModelBakery, BiFunction diskFullModelBakery, BiFunction diskDisconnectedModelBakery, RenderTypeGroup renderTypes) { super(originalModel); this.baseConnectedModelBakery = baseConnectedModelBakery; this.baseDisconnectedModelBakery = baseDisconnectedModelBakery; this.diskModelBakery = diskModelBakery; this.diskNearCapacityModelBakery = diskNearCapacityModelBakery; this.diskFullModelBakery = diskFullModelBakery; this.diskDisconnectedModelBakery = diskDisconnectedModelBakery; this.renderType = renderTypes; } @Override public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData data) { return ChunkRenderTypeSet.of(renderType.block()); } @Override @Nonnull public List getQuads(@Nullable final BlockState state, @Nullable final Direction side, @Nonnull final RandomSource rand, @Nonnull final ModelData extraData, @Nullable final RenderType renderType) { DiskState[] diskState = extraData.get(DiskManipulatorBlockEntity.DISK_STATE_PROPERTY); var color = RSBlocks.DISK_MANIPULATOR.getColorFromObject((DiskManipulatorBlock) state.getBlock()); if (diskState == null) { return super.getQuads(state, side, rand, extraData, renderType); } CacheKey key = new CacheKey(state, side, diskState, rand, color); return cache.getUnchecked(key); } private static class CacheKey { private final BlockState state; private final Direction side; private final DiskState[] diskState; private final RandomSource random; private final DyeColor color; CacheKey(BlockState state, @Nullable Direction side, DiskState[] diskState, RandomSource random, DyeColor color) { this.state = state; this.side = side; this.diskState = diskState; this.random = random; this.color = color; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } CacheKey cacheKey = (CacheKey) o; if (!state.equals(cacheKey.state)) { return false; } if (side != cacheKey.side) { return false; } if (color != cacheKey.color) { return false; } return Arrays.equals(diskState, cacheKey.diskState); } @Override public int hashCode() { int result = state.hashCode(); result = 31 * result + (side != null ? side.hashCode() : 0); result = 31 * result + Arrays.hashCode(diskState); return result; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/PatternBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.google.common.collect.ImmutableList; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPatternRenderHandler; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.item.PatternItem; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.model.BakedModelWrapper; import javax.annotation.Nullable; public class PatternBakedModel extends BakedModelWrapper { public PatternBakedModel(BakedModel base) { super(base); } public static boolean canDisplayOutput(ItemStack patternStack, ICraftingPattern pattern) { if (pattern.isValid() && pattern.getOutputs().size() == 1) { for (ICraftingPatternRenderHandler renderHandler : API.instance().getPatternRenderHandlers()) { if (renderHandler.canRenderOutput(patternStack)) { return true; } } } return false; } @Override public ItemOverrides getOverrides() { return new ItemOverrides() { @Nullable @Override public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { if (entity != null) { ICraftingPattern pattern = PatternItem.fromCache(entity.level(), stack); if (canDisplayOutput(stack, pattern)) { ItemStack outputToRender = pattern.getOutputs().get(0); return Minecraft.getInstance().getItemRenderer().getModel(outputToRender, level, entity, p); } } return super.resolve(model, stack, level, entity, p); } @Override public ImmutableList getOverrides() { return originalModel.getOverrides().getOverrides(); } }; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/PortableGridBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.block.PortableGridBlock; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGrid; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridDiskState; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.ChunkRenderTypeSet; import net.neoforged.neoforge.client.RenderTypeGroup; import net.neoforged.neoforge.client.model.BakedModelWrapper; import net.neoforged.neoforge.client.model.data.ModelData; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.function.Function; public class PortableGridBakedModel extends BakedModelWrapper { private final Function baseConnectedModelBakery; private final Function baseDisconnectedModelBakery; private final Function diskModelBakery; private final Function diskNearCapacityModelBakery; private final Function diskFullModelBakery; private final Function diskDisconnectedModelBakery; private final RenderTypeGroup renderTypes; private final CustomItemOverrideList itemOverrideList = new CustomItemOverrideList(); private final LoadingCache> cache = CacheBuilder.newBuilder().build(new CacheLoader>() { @Override @SuppressWarnings("deprecation") public List load(@Nonnull CacheKey key) { Direction direction = key.state.getValue(RSBlocks.PORTABLE_GRID.get().getDirection().getProperty()); boolean active = key.state.getValue(PortableGridBlock.ACTIVE); PortableGridDiskState diskState = key.state.getValue(PortableGridBlock.DISK_STATE); List quads = new ArrayList<>((active ? baseConnectedModelBakery : baseDisconnectedModelBakery) .apply(direction).getQuads(key.state, key.side, key.random)); Function diskModel = getDiskModelBakery(diskState); if (diskModel != null) { quads.addAll(diskModel.apply(direction).getQuads(key.state, key.side, key.random)); } return quads; } }); public PortableGridBakedModel(BakedModel baseModel, Function baseConnectedModelBakery, Function baseDisconnectedModelBakery, Function diskModelBakery, Function diskNearCapacityModelBakery, Function diskFullModelBakery, Function diskDisconnectedModelBakery, RenderTypeGroup renderTypes) { super(baseModel); this.baseConnectedModelBakery = baseConnectedModelBakery; this.baseDisconnectedModelBakery = baseDisconnectedModelBakery; this.diskModelBakery = diskModelBakery; this.diskNearCapacityModelBakery = diskNearCapacityModelBakery; this.diskFullModelBakery = diskFullModelBakery; this.diskDisconnectedModelBakery = diskDisconnectedModelBakery; this.renderTypes = renderTypes; } @Nullable private Function getDiskModelBakery(PortableGridDiskState state) { return switch (state) { case NORMAL -> diskModelBakery; case NEAR_CAPACITY -> diskNearCapacityModelBakery; case FULL -> diskFullModelBakery; case DISCONNECTED -> diskDisconnectedModelBakery; case NONE -> null; }; } @Override public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData data) { return ChunkRenderTypeSet.of(renderTypes.block()); } @Override public ItemOverrides getOverrides() { return itemOverrideList; } @Override public List getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource rand, ModelData extraData, @Nullable RenderType renderType) { if (state != null) { return cache.getUnchecked(new CacheKey(state, side, rand)); } return super.getQuads(state, side, rand, extraData, renderType); } private static class CacheKey { private final BlockState state; private final Direction side; private final RandomSource random; public CacheKey(BlockState state, Direction side, RandomSource random) { this.state = state; this.side = side; this.random = random; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CacheKey cacheKey = (CacheKey) o; return state.equals(cacheKey.state) && side == cacheKey.side && random.equals(cacheKey.random); } @Override public int hashCode() { return Objects.hash(state, side, random); } } private class CustomItemOverrideList extends ItemOverrides { @Nullable @Override public BakedModel resolve(BakedModel model, ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int p) { PortableGrid portableGrid = new PortableGrid(null, stack, new PlayerSlot(-1)); Function diskModelBakery = getDiskModelBakery(portableGrid.getDiskState()); BakedModel diskModel = diskModelBakery == null ? null : diskModelBakery.apply(Direction.NORTH); if (portableGrid.isGridActive()) { return new PortableGridItemBakedModel( baseConnectedModelBakery.apply(Direction.NORTH), diskModel ); } else { return new PortableGridItemBakedModel( baseDisconnectedModelBakery.apply(Direction.NORTH), diskModel ); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/model/baked/PortableGridItemBakedModel.java ================================================ package com.refinedmods.refinedstorage.render.model.baked; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemOverrides; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.util.RandomSource; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.BakedModelWrapper; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class PortableGridItemBakedModel extends BakedModelWrapper { @Nullable private final BakedModel disk; public PortableGridItemBakedModel(BakedModel base, @Nullable BakedModel disk) { super(base); this.disk = disk; } @Override public ItemOverrides getOverrides() { return ItemOverrides.EMPTY; } @Override @Nonnull @SuppressWarnings("deprecation") public List getQuads(@Nullable BlockState state, @Nullable Direction side, @Nonnull RandomSource rand) { List quads = new ArrayList<>(super.getQuads(state, side, rand)); if (disk != null) { quads.addAll(disk.getQuads(state, side, rand)); } return quads; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/resourcepack/RSResourcePackSection.java ================================================ package com.refinedmods.refinedstorage.render.resourcepack; public class RSResourcePackSection { public static final RSResourcePackSectionDeserializer DESERIALIZER = new RSResourcePackSectionDeserializer(); private final int primaryColor; private final int secondaryColor; public RSResourcePackSection(int primaryColor, int secondaryColor) { this.primaryColor = primaryColor; this.secondaryColor = secondaryColor; } public int getPrimaryColor() { return primaryColor; } public int getSecondaryColor() { return secondaryColor; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/resourcepack/RSResourcePackSectionDeserializer.java ================================================ package com.refinedmods.refinedstorage.render.resourcepack; import com.google.gson.JsonObject; import net.minecraft.server.packs.metadata.MetadataSectionSerializer; public class RSResourcePackSectionDeserializer implements MetadataSectionSerializer { @Override public String getMetadataSectionName() { return "refinedstorage"; } @Override public RSResourcePackSection fromJson(JsonObject json) { int primaryColor = -1; int secondaryColor = -1; if (json.has("primary_color")) { primaryColor = json.getAsJsonPrimitive("primary_color").getAsInt(); } if (json.has("secondary_color")) { secondaryColor = json.getAsJsonPrimitive("secondary_color").getAsInt(); } return new RSResourcePackSection(primaryColor, secondaryColor); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/render/resourcepack/ResourcePackListener.java ================================================ package com.refinedmods.refinedstorage.render.resourcepack; import com.refinedmods.refinedstorage.render.RenderSettings; import net.minecraft.client.Minecraft; import net.minecraft.server.packs.repository.Pack; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.SimplePreparableReloadListener; import net.minecraft.util.profiling.ProfilerFiller; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; import java.io.IOException; public class ResourcePackListener extends SimplePreparableReloadListener { private final Logger logger = LogManager.getLogger(getClass()); @Override protected RSResourcePackSection prepare(ResourceManager resourceManager, ProfilerFiller profiler) { for (Pack info : Minecraft.getInstance().getResourcePackRepository().getSelectedPacks()) { try { RSResourcePackSection section = info.open().getMetadataSection(RSResourcePackSection.DESERIALIZER); if (section != null) { return section; } } catch (IOException e) { logger.error("Could not read Refined Storage resource pack section", e); } } return null; } @Override protected void apply(@Nullable RSResourcePackSection section, ResourceManager resourceManager, ProfilerFiller profiler) { if (section != null) { RenderSettings.INSTANCE.setColors(section.getPrimaryColor(), section.getSecondaryColor()); } else { RenderSettings.INSTANCE.setColors(-1, -1); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/AmountSpecifyingScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.render.RenderSettings; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.glfw.GLFW; public abstract class AmountSpecifyingScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/amount_specifying.png"); private final BaseScreen parent; protected EditBox amountField; protected Button okButton; protected Button cancelButton; protected AmountSpecifyingScreen(BaseScreen parent, T container, int width, int height, Inventory playerInventory, Component title) { super(container, width, height, playerInventory, title); this.parent = parent; } protected abstract Component getOkButtonText(); protected ResourceLocation getTexture() { return TEXTURE; } protected abstract int[] getIncrements(); protected abstract int getDefaultAmount(); protected abstract boolean canAmountGoNegative(); protected abstract int getMaxAmount(); protected Pair getAmountPos() { return Pair.of(7 + 2, 50 + 1); } protected Pair getOkCancelPos() { return Pair.of(114, 33); } protected int getOkCancelButtonWidth() { return 50; } @Override public void onPostInit(int x, int y) { Pair pos = getOkCancelPos(); okButton = addButton(x + pos.getLeft(), y + pos.getRight(), getOkCancelButtonWidth(), 20, getOkButtonText(), true, true, btn -> onOkButtonPressed(hasShiftDown())); cancelButton = addButton(x + pos.getLeft(), y + pos.getRight() + 24, getOkCancelButtonWidth(), 20, Component.translatable("gui.cancel"), true, true, btn -> close()); amountField = new EditBox(font, x + getAmountPos().getLeft(), y + getAmountPos().getRight(), 69 - 6, font.lineHeight, Component.literal("")); amountField.setBordered(false); amountField.setVisible(true); amountField.setValue(String.valueOf(getDefaultAmount())); amountField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor()); amountField.setCanLoseFocus(false); amountField.setFocused(true); amountField.setResponder(text -> { int amount = 0; try { amount = Integer.parseInt(amountField.getValue()); } catch (NumberFormatException e) { // NO OP } if (amount > getMaxAmount()) { amountField.setValue(String.valueOf(getMaxAmount())); } }); addRenderableWidget(amountField); setFocused(amountField); int[] increments = getIncrements(); int xx = 7; int width = 30; for (int i = 0; i < 3; ++i) { int increment = increments[i]; Component text = Component.literal("+" + increment); if (text.getString().equals("+1000")) { text = Component.literal("+1B"); } addButton(x + xx, y + 20, width, 20, text, true, true, btn -> onIncrementButtonClicked(increment)); xx += width + 3; } xx = 7; for (int i = 0; i < 3; ++i) { int increment = increments[i]; Component text = Component.literal("-" + increment); if (text.getString().equals("-1000")) { text = Component.literal("-1B"); } addButton(x + xx, y + imageHeight - 20 - 7, width, 20, text, true, true, btn -> onIncrementButtonClicked(-increment)); xx += width + 3; } } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (key == GLFW.GLFW_KEY_ESCAPE) { close(); return true; } if ((key == GLFW.GLFW_KEY_ENTER || key == GLFW.GLFW_KEY_KP_ENTER) && amountField.isFocused()) { onOkButtonPressed(hasShiftDown()); return true; } if (amountField.keyPressed(key, scanCode, modifiers)) { return true; } return super.keyPressed(key, scanCode, modifiers); } private void onIncrementButtonClicked(int increment) { int oldAmount = 0; try { oldAmount = Integer.parseInt(amountField.getValue()); } catch (NumberFormatException e) { // NO OP } int newAmount = increment; if (!canAmountGoNegative()) { newAmount = Math.max(1, ((oldAmount == 1 && newAmount != 1) ? 0 : oldAmount) + newAmount); } else { newAmount = oldAmount + newAmount; } if (newAmount > getMaxAmount()) { newAmount = getMaxAmount(); } amountField.setValue(String.valueOf(newAmount)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(getTexture(), x, y, 0, 0, imageWidth, imageHeight); amountField.render(graphics, 0, 0, 0); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); } protected void onOkButtonPressed(boolean shiftDown) { // NO OP } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { if (delta > 0) { onIncrementButtonClicked(1); } else { onIncrementButtonClicked(-1); } return super.mouseScrolled(x, y, z, delta); } public void close() { minecraft.setScreen(parent); } public BaseScreen getParent() { return parent; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/BaseScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.mojang.blaze3d.platform.InputConstants; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.container.slot.filter.FilterSlot; import com.refinedmods.refinedstorage.container.slot.filter.FluidFilterSlot; import com.refinedmods.refinedstorage.render.FluidRenderer; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.grid.AlternativesScreen; import com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.SideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.KeyMapping; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.ClickType; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.lwjgl.opengl.GL11; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import java.util.function.Consumer; import java.util.stream.Collectors; public abstract class BaseScreen extends AbstractContainerScreen { public static final ResourceLocation ICONS_TEXTURE = new ResourceLocation(RS.ID, "textures/icons.png"); private static final int Z_LEVEL_QTY = 300; private static final Map, Queue>> ACTIONS = new HashMap<>(); private static final Component ALTERNATIVES_TEXT = Component.translatable("gui.refinedstorage.alternatives"); protected final Inventory inventory; private final List sideButtons = new ArrayList<>(); private final Logger logger = LogManager.getLogger(getClass()); private int sideButtonY; protected BaseScreen(T containerMenu, int xSize, int ySize, Inventory inventory, Component title) { super(containerMenu, inventory, title); this.imageWidth = xSize; this.imageHeight = ySize; this.inventory = inventory; } public static boolean isKeyDown(KeyMapping keybinding) { return !keybinding.isUnbound() && InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), keybinding.getKey().getValue()) && keybinding.getKeyConflictContext().isActive() && keybinding.getKeyModifier().isActive(keybinding.getKeyConflictContext()); } public static void executeLater(Class clazz, Consumer callback) { ACTIONS.computeIfAbsent(clazz, key -> new ArrayDeque<>()).add(callback); } public static void executeLater(Consumer callback) { executeLater(AbstractContainerScreen.class, callback); } public void runActions() { runActions(getClass()); runActions(AbstractContainerScreen.class); } private void runActions(Class clazz) { Queue> queue = ACTIONS.get(clazz); if (queue != null && !queue.isEmpty()) { Consumer callback; while ((callback = queue.poll()) != null) { callback.accept(this); } } } @Override public void init() { onPreInit(); super.init(); // TODO: what about craft tweaker buttons? this.clearWidgets(); sideButtonY = 6; sideButtons.clear(); onPostInit(leftPos, topPos); runActions(); } @Override protected void containerTick() { super.containerTick(); runActions(); tick(leftPos, topPos); } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { renderBackground(graphics, mouseX, mouseY, partialTicks); super.render(graphics, mouseX, mouseY, partialTicks); renderTooltip(graphics, mouseX, mouseY); } @Override protected void renderBg(GuiGraphics graphics, float renderPartialTicks, int mouseX, int mouseY) { RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); renderBackground(graphics, leftPos, topPos, mouseX, mouseY); for (int i = 0; i < this.menu.slots.size(); ++i) { Slot slot = menu.slots.get(i); if (slot.isActive() && slot instanceof FluidFilterSlot) { FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex()); if (!stack.isEmpty()) { FluidRenderer.INSTANCE.render(graphics, leftPos + slot.x, topPos + slot.y, stack); if (((FluidFilterSlot) slot).isSizeAllowed()) { renderQuantity(graphics, leftPos + slot.x, topPos + slot.y, API.instance().getQuantityFormatter().formatInBucketForm(stack.getAmount()), RenderSettings.INSTANCE.getSecondaryColor()); GL11.glDisable(GL11.GL_LIGHTING); } } } } } @Override protected void renderLabels(GuiGraphics graphics, int mouseX, int mouseY) { RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); mouseX -= leftPos; mouseY -= topPos; renderForeground(graphics, mouseX, mouseY); for (int i = 0; i < this.menu.slots.size(); ++i) { Slot slot = menu.slots.get(i); if (slot.isActive() && slot instanceof FluidFilterSlot) { FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex()); if (!stack.isEmpty() && RenderUtils.inBounds(slot.x, slot.y, 17, 17, mouseX, mouseY)) { renderTooltip(graphics, mouseX, mouseY, stack.getDisplayName().getString()); } } } } @Override protected void slotClicked(Slot slot, int slotId, int mouseButton, ClickType type) { boolean valid = type != ClickType.QUICK_MOVE && minecraft.player.containerMenu.getCarried().isEmpty(); if (valid && slot instanceof FilterSlot && slot.isActive() && ((FilterSlot) slot).isSizeAllowed()) { if (!slot.getItem().isEmpty()) { if (((FilterSlot) slot).isAlternativesAllowed() && hasControlDown()) { minecraft.setScreen(new AlternativesScreen( this, minecraft.player, ALTERNATIVES_TEXT, slot.getItem(), slot.getSlotIndex() )); } else { minecraft.setScreen(new ItemAmountScreen( this, minecraft.player, slot.index, slot.getItem(), Math.min(slot.getMaxStackSize(), slot.getItem().getMaxStackSize()), ((FilterSlot) slot).isAlternativesAllowed() ? (parent -> new AlternativesScreen( parent, minecraft.player, ALTERNATIVES_TEXT, slot.getItem(), slot.getSlotIndex() )) : null )); } } } else if (valid && slot instanceof FluidFilterSlot && slot.isActive() && ((FluidFilterSlot) slot).isSizeAllowed()) { FluidStack stack = ((FluidFilterSlot) slot).getFluidInventory().getFluid(slot.getSlotIndex()); if (!stack.isEmpty()) { if (((FluidFilterSlot) slot).isAlternativesAllowed() && hasControlDown()) { minecraft.setScreen(new AlternativesScreen( this, minecraft.player, ALTERNATIVES_TEXT, stack, slot.getSlotIndex() )); } else { minecraft.setScreen(new FluidAmountScreen( this, minecraft.player, slot.index, stack, ((FluidFilterSlot) slot).getFluidInventory().getMaxAmount(), ((FluidFilterSlot) slot).isAlternativesAllowed() ? (parent -> new AlternativesScreen( this, minecraft.player, ALTERNATIVES_TEXT, stack, slot.getSlotIndex() )) : null )); } } else { super.slotClicked(slot, slotId, mouseButton, type); } } else { super.slotClicked(slot, slotId, mouseButton, type); } } public SmallCheckboxWidget addCheckBox(int x, int y, Component text, boolean checked, Consumer onPress) { SmallCheckboxWidget checkBox = new SmallCheckboxWidget(x, y, text, checked, onPress); this.addRenderableWidget(checkBox); return checkBox; } public Button addButton(int x, int y, int w, int h, Component text, boolean enabled, boolean visible, Button.OnPress onPress) { Button button = Button.builder(text, onPress).pos(x, y).size(w, h).build(); button.active = enabled; button.visible = visible; addRenderableWidget(button); return button; } public void addSideButton(SideButton button) { button.setX(leftPos - button.getWidth() - 2); button.setY(topPos + sideButtonY); sideButtonY += button.getHeight() + 2; sideButtons.add(button); addRenderableWidget(button); } public List getSideButtons() { return sideButtons; } public void renderItem(GuiGraphics graphics, int x, int y, ItemStack stack) { renderItem(graphics, x, y, stack, false, null, 0); } public void renderItem(GuiGraphics graphics, int x, int y, ItemStack stack, boolean overlay, @Nullable String text, int textColor) { try { graphics.renderItem(stack, x, y); if (overlay) { graphics.renderItemDecorations(font, stack, x, y, ""); } if (text != null) { renderQuantity(graphics, x, y, text, textColor); } } catch (Throwable t) { logger.warn("Couldn't render stack: {}", BuiltInRegistries.ITEM.getKey(stack.getItem())); } } public void renderQuantity(GuiGraphics graphics, int x, int y, String qty, int color) { boolean large = minecraft.isEnforceUnicode() || RS.CLIENT_CONFIG.getGrid().getLargeFont(); graphics.pose().pushPose(); graphics.pose().translate(x, y, Z_LEVEL_QTY); if (!large) { graphics.pose().scale(0.5F, 0.5F, 1); } graphics.drawString(font, qty, (large ? 16 : 30) - font.width(qty), large ? 8 : 22, color); graphics.pose().popPose(); } public void renderString(GuiGraphics graphics, int x, int y, String message) { renderString(graphics, x, y, message, RenderSettings.INSTANCE.getPrimaryColor()); } public void renderString(GuiGraphics graphics, int x, int y, String message, int color) { graphics.drawString(font, message, x, y, color, false); } public void renderTooltip(GuiGraphics graphics, int x, int y, String lines) { renderTooltip(graphics, ItemStack.EMPTY, x, y, lines); } public void renderTooltip(GuiGraphics graphics, @Nonnull ItemStack stack, int x, int y, String lines) { renderTooltip(graphics, stack, x, y, Arrays.stream(lines.split("\n")).map(Component::literal).collect(Collectors.toList())); } public void renderTooltip(GuiGraphics graphics, @Nonnull ItemStack stack, int x, int y, List lines) { graphics.renderComponentTooltip(font, lines, x, y, stack); } protected void onPreInit() { // NO OP } public abstract void onPostInit(int x, int y); public abstract void tick(int x, int y); public abstract void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY); public abstract void renderForeground(GuiGraphics graphics, int mouseX, int mouseY); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ConstructorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.ConstructorContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ConstructorDropSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class ConstructorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/constructor.png"); public ConstructorScreen(ConstructorContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new TypeSideButton(this, ConstructorBlockEntity.TYPE)); addSideButton(new ExactModeSideButton(this, ConstructorBlockEntity.COMPARE)); addSideButton(new ConstructorDropSideButton(this)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ControllerScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.apiimpl.network.Network; import com.refinedmods.refinedstorage.blockentity.ClientNode; import com.refinedmods.refinedstorage.blockentity.ControllerBlockEntity; import com.refinedmods.refinedstorage.container.ControllerContainerMenu; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import java.util.List; public class ControllerScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/controller.png"); private static final int VISIBLE_ROWS = 2; private static final int ENERGY_BAR_X = 8; private static final int ENERGY_BAR_Y = 20; private static final int ENERGY_BAR_WIDTH = 16; private static final int ENERGY_BAR_HEIGHT = 59; private final ScrollbarWidget scrollbar; public ControllerScreen(ControllerContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 181, inventory, title); this.scrollbar = new ScrollbarWidget(this, 157, 20, 12, 59); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, ControllerBlockEntity.REDSTONE_MODE)); } @Override public void tick(int x, int y) { scrollbar.setEnabled(getRows() > VISIBLE_ROWS); scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS); } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); int energyBarHeightNew = Network.getEnergyScaled(ControllerBlockEntity.ENERGY_STORED.getValue(), ControllerBlockEntity.ENERGY_CAPACITY.getValue(), ENERGY_BAR_HEIGHT); graphics.blit(TEXTURE, x + ENERGY_BAR_X, y + ENERGY_BAR_Y + ENERGY_BAR_HEIGHT - energyBarHeightNew, 178, ENERGY_BAR_HEIGHT - energyBarHeightNew, ENERGY_BAR_WIDTH, energyBarHeightNew); scrollbar.render(graphics); } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); super.mouseMoved(mx, my); } @Override public boolean mouseClicked(double mx, double my, int button) { return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button); } @Override public boolean mouseReleased(double mx, double my, int button) { return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 87, I18n.get("container.inventory")); int x = 33; int y = 26; int slot = scrollbar.getOffset() * 2; Lighting.setupFor3DItems(); List nodes = ControllerBlockEntity.NODES.getValue(); ClientNode hoveringNode = null; for (int i = 0; i < 4; ++i) { if (slot < nodes.size()) { ClientNode node = nodes.get(slot); renderItem(graphics, x, y + 5, node.getStack()); float scale = minecraft.isEnforceUnicode() ? 1F : 0.5F; final PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); renderString( graphics, RenderUtils.getOffsetOnScale(x + 1, scale), RenderUtils.getOffsetOnScale(y - 2, scale), trimNameIfNeeded(!minecraft.isEnforceUnicode(), node.getStack().getHoverName().getString()) ); renderString(graphics, RenderUtils.getOffsetOnScale(x + 21, scale), RenderUtils.getOffsetOnScale(y + 10, scale), node.getAmount() + "x"); poseStack.popPose(); if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY)) { hoveringNode = node; } } if (i == 1) { x = 33; y += 30; } else { x += 60; } slot++; } if (hoveringNode != null) { renderTooltip(graphics, mouseX, mouseY, I18n.get("misc.refinedstorage.energy_usage_minimal", hoveringNode.getEnergyUsage())); } if (RenderUtils.inBounds(ENERGY_BAR_X, ENERGY_BAR_Y, ENERGY_BAR_WIDTH, ENERGY_BAR_HEIGHT, mouseX, mouseY)) { 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())); } } private int getRows() { return Math.max(0, (int) Math.ceil((float) ControllerBlockEntity.NODES.getValue().size() / 2F)); } private String trimNameIfNeeded(boolean scaled, String name) { int max = scaled ? 19 : 12; if (name.length() > max) { name = name.substring(0, max) + "..."; } return name; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/CrafterBlockEntitySynchronizationClientListener.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.screen.widget.sidebutton.CrafterModeSideButton; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationClientListener; public class CrafterBlockEntitySynchronizationClientListener implements BlockEntitySynchronizationClientListener { @Override public void onChanged(boolean initial, Boolean hasRoot) { if (Boolean.FALSE.equals(hasRoot)) { BaseScreen.executeLater(CrafterScreen.class, gui -> gui.addSideButton(new CrafterModeSideButton(gui))); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/CrafterManagerScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode; import com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu; import com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.screen.widget.SearchWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.CrafterManagerSearchBoxModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.GridSizeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.Slot; import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak; import java.util.Map; @MouseTweaksDisableWheelTweak public class CrafterManagerScreen extends BaseScreen implements IScreenInfoProvider { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafter_manager.png"); private final CrafterManagerNetworkNode crafterManager; private ScrollbarWidget scrollbar; private SearchWidget searchField; public CrafterManagerScreen(CrafterManagerContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 193, 0, inventory, title); this.crafterManager = ((CrafterManagerBlockEntity) containerMenu.getBlockEntity()).getNode(); } @Override protected void onPreInit() { this.imageHeight = getTopHeight() + getBottomHeight() + (getVisibleRows() * 18); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new CrafterManagerSearchBoxModeSideButton(this)); addSideButton(new GridSizeSideButton(this, crafterManager::getSize, size -> BlockEntitySynchronizationManager.setParameter(CrafterManagerBlockEntity.SIZE, size))); this.scrollbar = new ScrollbarWidget(this, 174, getTopHeight(), 12, (getVisibleRows() * 18) - 2); this.scrollbar.addListener((oldOffset, newOffset) -> menu.initSlots(null)); menu.initSlots(null); int sx = x + 97 + 1; int sy = y + 6 + 1; if (searchField == null) { searchField = new SearchWidget(font, sx, sy, 88 - 6); searchField.setResponder(value -> { searchField.updateJei(); menu.initSlots(null); }); searchField.setMode(crafterManager.getSearchBoxMode()); } else { searchField.setX(sx); searchField.setY(sy); } addRenderableWidget(searchField); if (searchField.isFocused()) { setFocused(searchField); } } @Override public void tick(int x, int y) { scrollbar.setEnabled((getRows() - 1) >= getVisibleRows()); scrollbar.setMaxOffset(getRows() - getVisibleRows()); } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, getTopHeight()); int rows = getVisibleRows(); int yy = y; for (int i = 0; i < rows; ++i) { yy += 18; int yTextureStart = getTopHeight(); if (i > 0) { if (i == rows - 1) { yTextureStart += 18 * 2; } else { yTextureStart += 18; } } graphics.blit(TEXTURE, x, yy, 0, yTextureStart, imageWidth, 18); } yy += 18; graphics.blit(TEXTURE, x, yy, 0, getTopHeight() + (18 * 3), imageWidth, getBottomHeight()); if (crafterManager.isActiveOnClient()) { for (Slot slot : menu.slots) { if (slot instanceof CrafterManagerSlot && slot.isActive()) { graphics.blit(TEXTURE, x + slot.x - 1, y + slot.y - 1, 0, 193, 18, 18); } } } searchField.render(graphics, 0, 0, 0); scrollbar.render(graphics); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, getYPlayerInventory() - 12, I18n.get("container.inventory")); if (crafterManager.isActiveOnClient()) { for (Map.Entry heading : menu.getHeadings().entrySet()) { int y = heading.getValue(); if (y >= getTopHeight() - 1 && y < getTopHeight() + getVisibleRows() * 18 - 1) { RenderSystem.setShaderColor(1, 1, 1, 1); graphics.blit(TEXTURE, 7, y, 0, 174, 18 * 9, 18); renderString(graphics, 7 + 4, y + 6, RenderUtils.shorten(I18n.get(heading.getKey()), 25)); } } } } @Override public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) { if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { return true; } return super.mouseClicked(mouseX, mouseY, clickedButton); } @Override public boolean charTyped(char unknown1, int unknown2) { if (searchField.charTyped(unknown1, unknown2)) { return true; } return super.charTyped(unknown1, unknown2); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (searchField.keyPressed(key, scanCode, modifiers)) { return true; } return super.keyPressed(key, scanCode, modifiers); } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); super.mouseMoved(mx, my); } @Override public boolean mouseReleased(double mx, double my, int button) { return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } public SearchWidget getSearchField() { return searchField; } public CrafterManagerNetworkNode getCrafterManager() { return crafterManager; } @Override public int getTopHeight() { return 19; } @Override public int getBottomHeight() { return 99; } @Override public int getVisibleRows() { switch (crafterManager.getSize()) { case IGrid.SIZE_STRETCH: int screenSpaceAvailable = height - getTopHeight() - getBottomHeight(); return Math.max(3, Math.min((screenSpaceAvailable / 18) - 3, RS.CLIENT_CONFIG.getCrafterManager().getMaxRowsStretch())); case IGrid.SIZE_SMALL: return 3; case IGrid.SIZE_MEDIUM: return 5; case IGrid.SIZE_LARGE: return 8; default: return 3; } } @Override public int getRows() { return !crafterManager.isActiveOnClient() ? 0 : menu.getRows(); } @Override public int getCurrentOffset() { return scrollbar == null ? 0 : scrollbar.getOffset(); } @Override public String getSearchFieldText() { return searchField == null ? "" : searchField.getValue(); } @Override public int getYPlayerInventory() { return getTopHeight() + (getVisibleRows() * 18) + 16; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/CrafterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.CrafterContainerMenu; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class CrafterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafter.png"); public CrafterScreen(CrafterContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 137, inventory, title); } @Override public void onPostInit(int x, int y) { // NO OP } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, RenderUtils.shorten(title.getString(), 26)); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/CraftingMonitorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.google.common.collect.Lists; import com.mojang.blaze3d.platform.Lighting; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.craftingmonitor.ICraftingMonitorElement; import com.refinedmods.refinedstorage.api.autocrafting.task.ICraftingRequestInfo; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.api.render.IElementDrawer; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.render.CraftingMonitorElementDrawers; import com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers; import com.refinedmods.refinedstorage.blockentity.craftingmonitor.ICraftingMonitor; import com.refinedmods.refinedstorage.container.CraftingMonitorContainerMenu; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorCancelMessage; import com.refinedmods.refinedstorage.network.craftingmonitor.CraftingMonitorSyncTask; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.screen.widget.TabListWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import javax.annotation.Nullable; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.UUID; public class CraftingMonitorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafting_preview.png"); private static final int ROWS = 5; private static final int ITEM_WIDTH = 73; private static final int ITEM_HEIGHT = 29; private final ScrollbarWidget scrollbar; private final ICraftingMonitor craftingMonitor; private final TabListWidget tabs; private final IElementDrawers drawers = new CraftingMonitorElementDrawers(this, ITEM_WIDTH, ITEM_HEIGHT); private Button cancelButton; private Button cancelAllButton; private List tasks = Collections.emptyList(); public CraftingMonitorScreen(CraftingMonitorContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 254, 201, inventory, title); this.craftingMonitor = containerMenu.getCraftingMonitor(); 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, () -> { IGridTab tab = getCurrentTab(); if (tab == null) { return -1; } return tasks.indexOf(tab); }, ICraftingMonitor.TABS_PER_PAGE); this.tabs.addListener(new TabListWidget.ITabListListener() { @Override public void onSelectionChanged(int tab) { craftingMonitor.onTabSelectionChanged(Optional.of(((Task) tasks.get(tab)).id)); scrollbar.setOffset(0); } @Override public void onPageChanged(int page) { craftingMonitor.onTabPageChanged(page); } }); this.scrollbar = new ScrollbarWidget(this, 235, 20, 12, 149); } public void setTasks(List tasks) { this.tasks = tasks.stream().map(Task::new).collect(Lists::newArrayList, List::add, List::addAll); } public List getElements() { if (!craftingMonitor.isActiveOnClient()) { return Collections.emptyList(); } IGridTab tab = getCurrentTab(); if (tab == null) { return Collections.emptyList(); } return ((Task) tab).elements; } @Override public void onPostInit(int x, int y) { this.tabs.init(imageWidth); if (craftingMonitor.getRedstoneModeParameter() != null) { addSideButton(new RedstoneModeSideButton(this, craftingMonitor.getRedstoneModeParameter())); } Component cancel = Component.translatable("gui.cancel"); Component cancelAll = Component.translatable("misc.refinedstorage.cancel_all"); int cancelButtonWidth = 14 + font.width(cancel.getString()); int cancelAllButtonWidth = 14 + font.width(cancelAll.getString()); this.cancelButton = addButton(x + 7, y + 201 - 20 - 7, cancelButtonWidth, 20, cancel, false, true, btn -> { if (hasValidTabSelected()) { RS.NETWORK_HANDLER.sendToServer(new CraftingMonitorCancelMessage(((Task) getCurrentTab()).id)); } }); this.cancelAllButton = addButton(x + 7 + cancelButtonWidth + 4, y + 201 - 20 - 7, cancelAllButtonWidth, 20, cancelAll, false, true, btn -> { if (!tasks.isEmpty()) { RS.NETWORK_HANDLER.sendToServer(new CraftingMonitorCancelMessage(null)); } }); } private void updateScrollbar() { if (scrollbar != null) { scrollbar.setEnabled(getRows() > ROWS); scrollbar.setMaxOffset(getRows() - ROWS); } } private int getRows() { return Math.max(0, (int) Math.ceil((float) getElements().size() / 3F)); } @Override public void tick(int x, int y) { updateScrollbar(); this.tabs.update(); if (cancelButton != null) { cancelButton.active = hasValidTabSelected(); } if (cancelAllButton != null) { cancelAllButton.active = !tasks.isEmpty(); } } private boolean hasValidTabSelected() { return getCurrentTab() != null; } @Nullable private IGridTab getCurrentTab() { Optional currentTab = craftingMonitor.getTabSelected(); if (currentTab.isPresent()) { IGridTab tab = getTabById(currentTab.get()); if (tab != null) { return tab; } } if (tasks.isEmpty()) { return null; } return tasks.get(0); } @Nullable private IGridTab getTabById(UUID id) { return tasks.stream().filter(t -> ((Task) t).id.equals(id)).findFirst().orElse(null); } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { if (craftingMonitor.isActiveOnClient()) { tabs.drawBackground(graphics, x, y - tabs.getHeight()); } graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); scrollbar.render(graphics); tabs.drawForeground(graphics, x, y - tabs.getHeight(), mouseX, mouseY, craftingMonitor.isActiveOnClient()); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); int item = scrollbar != null ? scrollbar.getOffset() * 3 : 0; Lighting.setupFor3DItems(); int x = 7; int y = 20; List tooltip = null; for (int i = 0; i < 3 * 5; ++i) { if (item < getElements().size()) { ICraftingMonitorElement element = getElements().get(item); element.draw(graphics, x, y, drawers); if (RenderUtils.inBounds(x, y, ITEM_WIDTH, ITEM_HEIGHT, mouseX, mouseY)) { tooltip = element.getTooltip(); } if ((i + 1) % 3 == 0) { x = 7; y += 30; } else { x += 74; } } item++; } if (tooltip != null && !tooltip.isEmpty()) { renderTooltip(graphics, ItemStack.EMPTY, mouseX, mouseY, tooltip); } tabs.drawTooltip(graphics, font, mouseX, mouseY); } @Override public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) { if (tabs.mouseClicked()) { return true; } if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { return true; } return super.mouseClicked(mouseX, mouseY, clickedButton); } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); super.mouseMoved(mx, my); } @Override public boolean mouseReleased(double mx, double my, int button) { return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } public static class Task implements IGridTab { private final UUID id; private final ICraftingRequestInfo requested; private final int qty; private final long executionStarted; private final int completionPercentage; private final List elements; public Task(CraftingMonitorSyncTask syncTask) { this.id = syncTask.id(); this.requested = syncTask.requestInfo(); this.qty = syncTask.quantity(); this.executionStarted = syncTask.startTime(); this.completionPercentage = syncTask.completionPercentage(); this.elements = syncTask.elements(); } @Override public void drawTooltip(Font font, GuiGraphics graphics, int x, int y) { List lines = Lists.newArrayList(requested.getItem() != null ? requested.getItem().getHoverName() : requested.getFluid().getDisplayName()); int totalSecs = (int) (System.currentTimeMillis() - executionStarted) / 1000; int hours = totalSecs / 3600; int minutes = (totalSecs % 3600) / 60; int seconds = totalSecs % 60; lines.add(Component.translatable( "gui.refinedstorage.crafting_monitor.tooltip.requested", requested.getFluid() != null ? API.instance().getQuantityFormatter().formatInBucketForm(qty) : API.instance().getQuantityFormatter().format(qty) ).withStyle(ChatFormatting.GRAY)); if (hours > 0) { lines.add(Component.literal(String.format("%02d:%02d:%02d", hours, minutes, seconds)).withStyle(ChatFormatting.GRAY)); } else { lines.add(Component.literal(String.format("%02d:%02d", minutes, seconds)).withStyle(ChatFormatting.GRAY)); } lines.add(Component.literal(String.format("%d%%", completionPercentage)).withStyle(ChatFormatting.GRAY)); graphics.renderComponentTooltip(font, lines, x, y); } @Override public List getFilters() { throw new UnsupportedOperationException(); } @Override public void drawIcon(GuiGraphics graphics, int x, int y, IElementDrawer itemDrawer, IElementDrawer fluidDrawer) { if (requested.getItem() != null) { Lighting.setupFor3DItems(); itemDrawer.draw(graphics, x, y, requested.getItem()); } else { fluidDrawer.draw(graphics, x, y, requested.getFluid()); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/DestructorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.DestructorContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.*; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class DestructorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/destructor.png"); public DestructorScreen(DestructorContainerMenu containerMenu, Inventory playerInventory, Component title) { super(containerMenu, 211, 137, playerInventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new TypeSideButton(this, DestructorBlockEntity.TYPE)); addSideButton(new WhitelistBlacklistSideButton(this, DestructorBlockEntity.WHITELIST_BLACKLIST)); addSideButton(new ExactModeSideButton(this, DestructorBlockEntity.COMPARE)); addSideButton(new DestructorPickupSideButton(this)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/DetectorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.container.DetectorContainerMenu; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.widget.sidebutton.DetectorModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import org.lwjgl.glfw.GLFW; public class DetectorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/detector.png"); private EditBox amountField; public DetectorScreen(DetectorContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new TypeSideButton(this, DetectorBlockEntity.TYPE)); addSideButton(new DetectorModeSideButton(this)); addSideButton(new ExactModeSideButton(this, DetectorBlockEntity.COMPARE)); amountField = new EditBox(font, x + 41 + 1, y + 23 + 1, 50, font.lineHeight, Component.literal("")); amountField.setValue(String.valueOf(DetectorBlockEntity.AMOUNT.getValue())); amountField.setBordered(false); amountField.setVisible(true); amountField.setCanLoseFocus(true); amountField.setFocused(false); amountField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor()); amountField.setResponder(value -> { try { int result = Integer.parseInt(value); BlockEntitySynchronizationManager.setParameter(DetectorBlockEntity.AMOUNT, result); } catch (NumberFormatException e) { // NO OP } }); addRenderableWidget(amountField); } public void updateAmountField(int amount) { amountField.setValue(String.valueOf(amount)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (key == GLFW.GLFW_KEY_ESCAPE) { minecraft.player.closeContainer(); return true; } if (amountField.keyPressed(key, scanCode, modifiers) || amountField.canConsumeInput()) { return true; } return super.keyPressed(key, scanCode, modifiers); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/DiskDriveScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.DiskDriveBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.DiskDriveContainerMenu; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class DiskDriveScreen extends StorageScreen { public DiskDriveScreen(DiskDriveContainerMenu containerMenu, Inventory inventory, Component title) { super( containerMenu, inventory, title, new ResourceLocation(RS.ID, "textures/gui/disk_drive.png"), new StorageScreenSynchronizationParameters( DiskDriveBlockEntity.TYPE, NetworkNodeBlockEntity.REDSTONE_MODE, DiskDriveBlockEntity.COMPARE, DiskDriveBlockEntity.WHITELIST_BLACKLIST, DiskDriveBlockEntity.PRIORITY, DiskDriveBlockEntity.ACCESS_TYPE ), DiskDriveBlockEntity.STORED::getValue, DiskDriveBlockEntity.CAPACITY::getValue ); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 79, 42, I18n.get("gui.refinedstorage.disk_drive.disks")); super.renderForeground(graphics, mouseX, mouseY); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/DiskManipulatorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.*; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class DiskManipulatorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/disk_manipulator.png"); public DiskManipulatorScreen(DiskManipulatorContainerMenu containerMenu, Inventory playerInventory, Component title) { super(containerMenu, 211, 211, playerInventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new IoModeSideButton(this)); addSideButton(new TypeSideButton(this, DiskManipulatorBlockEntity.TYPE)); addSideButton(new WhitelistBlacklistSideButton(this, DiskManipulatorBlockEntity.WHITELIST_BLACKLIST)); addSideButton(new ExactModeSideButton(this, DiskManipulatorBlockEntity.COMPARE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 117, I18n.get("container.inventory")); renderString(graphics, 43, 45, I18n.get("gui.refinedstorage.disk_manipulator.in")); renderString(graphics, 115, 45, I18n.get("gui.refinedstorage.disk_manipulator.out")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/EmptyScreenInfoProvider.java ================================================ package com.refinedmods.refinedstorage.screen; public class EmptyScreenInfoProvider implements IScreenInfoProvider { @Override public int getVisibleRows() { return 3; } @Override public int getRows() { return 0; } @Override public int getCurrentOffset() { return 0; } @Override public String getSearchFieldText() { return ""; } @Override public int getTopHeight() { return 0; } @Override public int getBottomHeight() { return 0; } @Override public int getYPlayerInventory() { return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ExporterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.ExporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.ExporterContainerMenu; import com.refinedmods.refinedstorage.item.UpgradeItem; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class ExporterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/exporter.png"); private boolean hasRegulatorMode; public ExporterScreen(ExporterContainerMenu containerMenu, Inventory playerInventory, Component title) { super(containerMenu, 211, 137, playerInventory, title); this.hasRegulatorMode = hasRegulatorMode(); } private boolean hasRegulatorMode() { return ((ExporterBlockEntity) menu.getBlockEntity()).getNode().getUpgrades().hasUpgrade(UpgradeItem.Type.REGULATOR); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new TypeSideButton(this, ExporterBlockEntity.TYPE)); addSideButton(new ExactModeSideButton(this, ExporterBlockEntity.COMPARE)); } @Override public void tick(int x, int y) { boolean updatedHasRegulatorMode = hasRegulatorMode(); if (hasRegulatorMode != updatedHasRegulatorMode) { hasRegulatorMode = updatedHasRegulatorMode; menu.initSlots(); } } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ExternalStorageScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.ExternalStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.ExternalStorageContainerMenu; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class ExternalStorageScreen extends StorageScreen { public ExternalStorageScreen(ExternalStorageContainerMenu containerMenu, Inventory inventory, Component title) { super( containerMenu, inventory, title, new ResourceLocation(RS.ID, "textures/gui/storage.png"), new StorageScreenSynchronizationParameters( ExternalStorageBlockEntity.TYPE, NetworkNodeBlockEntity.REDSTONE_MODE, ExternalStorageBlockEntity.COMPARE, ExternalStorageBlockEntity.WHITELIST_BLACKLIST, ExternalStorageBlockEntity.PRIORITY, ExternalStorageBlockEntity.ACCESS_TYPE ), ExternalStorageBlockEntity.STORED::getValue, ExternalStorageBlockEntity.CAPACITY::getValue ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/FilterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.container.FilterContainerMenu; import com.refinedmods.refinedstorage.item.FilterItem; import com.refinedmods.refinedstorage.network.FilterUpdateMessage; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.FilterTypeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import org.lwjgl.glfw.GLFW; public class FilterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/filter.png"); private final ItemStack stack; private final String name; private int compare; private int mode; private boolean modFilter; private int type; private SmallCheckboxWidget modFilterCheckBox; private Button modeButton; private EditBox nameField; public FilterScreen(FilterContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 231, inventory, title); this.stack = containerMenu.getFilterItem(); this.compare = FilterItem.getCompare(containerMenu.getFilterItem()); this.mode = FilterItem.getMode(containerMenu.getFilterItem()); this.modFilter = FilterItem.isModFilter(containerMenu.getFilterItem()); this.name = FilterItem.getFilterName(containerMenu.getFilterItem()); this.type = FilterItem.getType(containerMenu.getFilterItem()); } @Override public void onPostInit(int x, int y) { addCheckBox(x + 7, y + 77, Component.translatable("gui.refinedstorage.filter.compare_nbt"), (compare & IComparer.COMPARE_NBT) == IComparer.COMPARE_NBT, btn -> { compare ^= IComparer.COMPARE_NBT; sendUpdate(); }); modFilterCheckBox = addCheckBox(0, y + 71 + 25, Component.translatable("gui.refinedstorage.filter.mod_filter"), modFilter, btn -> { modFilter = !modFilter; sendUpdate(); }); modeButton = addButton(x + 7, y + 71 + 21, 0, 20, Component.literal(""), true, true, btn -> { mode = mode == IFilter.MODE_WHITELIST ? IFilter.MODE_BLACKLIST : IFilter.MODE_WHITELIST; updateModeButton(mode); sendUpdate(); }); updateModeButton(mode); nameField = new EditBox(font, x + 34, y + 121, 137 - 6, font.lineHeight, Component.literal("")); nameField.setValue(name); nameField.setBordered(false); nameField.setVisible(true); nameField.setCanLoseFocus(true); nameField.setFocused(false); nameField.setTextColor(RenderSettings.INSTANCE.getSecondaryColor()); nameField.setResponder(content -> sendUpdate()); addRenderableWidget(nameField); addSideButton(new FilterTypeSideButton(this)); } private void updateModeButton(int mode) { Component text = mode == IFilter.MODE_WHITELIST ? Component.translatable("sidebutton.refinedstorage.mode.whitelist") : Component.translatable("sidebutton.refinedstorage.mode.blacklist"); modeButton.setWidth(font.width(text.getString()) + 12); modeButton.setMessage(text); modFilterCheckBox.setX(modeButton.getX() + modeButton.getWidth() + 4); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (key == GLFW.GLFW_KEY_ESCAPE) { minecraft.player.closeContainer(); return true; } if (nameField.keyPressed(key, scanCode, modifiers) || nameField.canConsumeInput()) { return true; } return super.keyPressed(key, scanCode, modifiers); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 137, I18n.get("container.inventory")); } public int getType() { return type; } public void setType(int type) { this.type = type; FilterItem.setType(stack, type); } public void sendUpdate() { RS.NETWORK_HANDLER.sendToServer(new FilterUpdateMessage(compare, mode, modFilter, nameField.getValue(), type)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/FluidAmountScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.FluidAmountContainerMenu; import com.refinedmods.refinedstorage.network.SetFluidFilterSlotMessage; import com.refinedmods.refinedstorage.util.StackUtils; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; import java.util.function.UnaryOperator; public class FluidAmountScreen extends AmountSpecifyingScreen { private static final ResourceLocation TEXTURE_WIDE = new ResourceLocation(RS.ID, "textures/gui/amount_specifying_wide.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/amount_specifying.png"); private final int containerSlot; private final FluidStack stack; private final int maxAmount; @Nullable private final UnaryOperator alternativesScreenFactory; public FluidAmountScreen(BaseScreen parent, Player player, int containerSlot, FluidStack stack, int maxAmount, @Nullable UnaryOperator alternativesScreenFactory) { super(parent, new FluidAmountContainerMenu(player, stack), alternativesScreenFactory != null ? 194 : 172, 99, player.getInventory(), Component.translatable("gui.refinedstorage.fluid_amount")); this.containerSlot = containerSlot; this.stack = stack; this.maxAmount = maxAmount; this.alternativesScreenFactory = alternativesScreenFactory; } @Override protected int getOkCancelButtonWidth() { return alternativesScreenFactory != null ? 75 : super.getOkCancelButtonWidth(); } @Override public void onPostInit(int x, int y) { super.onPostInit(x, y); if (alternativesScreenFactory != null) { addButton(x + 114, cancelButton.getY() + 24, getOkCancelButtonWidth(), 20, Component.translatable("gui.refinedstorage.alternatives"), true, true, btn -> minecraft.setScreen(alternativesScreenFactory.apply(this))); } } @Override protected Pair getOkCancelPos() { if (alternativesScreenFactory == null) { return super.getOkCancelPos(); } return Pair.of(114, 22); } @Override protected int getDefaultAmount() { return stack.getAmount(); } @Override protected boolean canAmountGoNegative() { return false; } @Override protected int getMaxAmount() { return maxAmount; } @Override protected Component getOkButtonText() { return Component.translatable("misc.refinedstorage.set"); } @Override protected ResourceLocation getTexture() { return alternativesScreenFactory != null ? TEXTURE_WIDE : TEXTURE; } @Override protected int[] getIncrements() { return new int[]{ 100, 500, 1000, -100, -500, -1000 }; } @Override protected void onOkButtonPressed(boolean shiftDown) { try { int amount = Integer.parseInt(amountField.getValue()); RS.NETWORK_HANDLER.sendToServer(new SetFluidFilterSlotMessage(containerSlot, StackUtils.copy(stack, amount))); close(); } catch (NumberFormatException e) { // NO OP } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/FluidInterfaceScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode; import com.refinedmods.refinedstorage.blockentity.FluidInterfaceBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.FluidInterfaceContainerMenu; import com.refinedmods.refinedstorage.render.FluidRenderer; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class FluidInterfaceScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/fluid_interface.png"); private static final FluidRenderer TANK_RENDERER = new FluidRenderer(FluidInterfaceNetworkNode.TANK_CAPACITY, 12, 47, 1); public FluidInterfaceScreen(FluidInterfaceContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 204, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); if (!FluidInterfaceBlockEntity.TANK_IN.getValue().isEmpty()) { TANK_RENDERER.render(graphics, x + 46, y + 56, FluidInterfaceBlockEntity.TANK_IN.getValue()); } if (!FluidInterfaceBlockEntity.TANK_OUT.getValue().isEmpty()) { TANK_RENDERER.render(graphics, x + 118, y + 56, FluidInterfaceBlockEntity.TANK_OUT.getValue()); } } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 43 + 4, 20, I18n.get("gui.refinedstorage.fluid_interface.in")); renderString(graphics, 115 + 1, 20, I18n.get("gui.refinedstorage.fluid_interface.out")); renderString(graphics, 7, 111, I18n.get("container.inventory")); if (RenderUtils.inBounds(46, 56, 12, 47, mouseX, mouseY) && !FluidInterfaceBlockEntity.TANK_IN.getValue().isEmpty()) { renderTooltip(graphics, mouseX, mouseY, FluidInterfaceBlockEntity.TANK_IN.getValue().getDisplayName().getString() + "\n" + ChatFormatting.GRAY + API.instance().getQuantityFormatter().formatInBucketForm(FluidInterfaceBlockEntity.TANK_IN.getValue().getAmount()) + ChatFormatting.RESET); } if (RenderUtils.inBounds(118, 56, 12, 47, mouseX, mouseY) && !FluidInterfaceBlockEntity.TANK_OUT.getValue().isEmpty()) { renderTooltip(graphics, mouseX, mouseY, FluidInterfaceBlockEntity.TANK_OUT.getValue().getDisplayName().getString() + "\n" + ChatFormatting.GRAY + API.instance().getQuantityFormatter().formatInBucketForm(FluidInterfaceBlockEntity.TANK_OUT.getValue().getAmount()) + ChatFormatting.RESET); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/FluidStorageBlockScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.FluidStorageBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.FluidStorageContainerMenu; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class FluidStorageBlockScreen extends StorageScreen { public FluidStorageBlockScreen(FluidStorageContainerMenu containerMenu, Inventory inventory, Component title) { super( containerMenu, inventory, title, new ResourceLocation(RS.ID, "textures/gui/storage.png"), new StorageScreenSynchronizationParameters( null, NetworkNodeBlockEntity.REDSTONE_MODE, FluidStorageBlockEntity.COMPARE, FluidStorageBlockEntity.WHITELIST_BLACKLIST, FluidStorageBlockEntity.PRIORITY, FluidStorageBlockEntity.ACCESS_TYPE ), FluidStorageBlockEntity.STORED::getValue, () -> (long) ((FluidStorageBlockEntity) containerMenu.getBlockEntity()).getFluidStorageType().getCapacity() ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/IScreenInfoProvider.java ================================================ package com.refinedmods.refinedstorage.screen; public interface IScreenInfoProvider { int getVisibleRows(); int getRows(); int getCurrentOffset(); String getSearchFieldText(); int getTopHeight(); int getBottomHeight(); int getYPlayerInventory(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ImporterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.ImporterBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.ImporterContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.WhitelistBlacklistSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class ImporterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/importer.png"); public ImporterScreen(ImporterContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new TypeSideButton(this, ImporterBlockEntity.TYPE)); addSideButton(new WhitelistBlacklistSideButton(this, ImporterBlockEntity.WHITELIST_BLACKLIST)); addSideButton(new ExactModeSideButton(this, ImporterBlockEntity.COMPARE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/InterfaceScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.InterfaceBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.InterfaceContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class InterfaceScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/interface.png"); public InterfaceScreen(InterfaceContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 217, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); addSideButton(new ExactModeSideButton(this, InterfaceBlockEntity.COMPARE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, I18n.get("gui.refinedstorage.interface.import")); renderString(graphics, 7, 42, I18n.get("gui.refinedstorage.interface.export")); renderString(graphics, 7, 122, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/ItemAmountScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.AmountContainerMenu; import com.refinedmods.refinedstorage.network.SetFilterSlotMessage; import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.items.ItemHandlerHelper; import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; import java.util.function.UnaryOperator; public class ItemAmountScreen extends AmountSpecifyingScreen { private static final ResourceLocation TEXTURE_WIDE = new ResourceLocation(RS.ID, "textures/gui/amount_specifying_wide.png"); private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/amount_specifying.png"); private final int containerSlot; private final ItemStack stack; private final int maxAmount; @Nullable private final UnaryOperator alternativesScreenFactory; public ItemAmountScreen(BaseScreen parent, Player player, int containerSlot, ItemStack stack, int maxAmount, @Nullable UnaryOperator alternativesScreenFactory) { super(parent, new AmountContainerMenu(player, stack), alternativesScreenFactory != null ? 194 : 172, 99, player.getInventory(), Component.translatable("gui.refinedstorage.item_amount")); this.containerSlot = containerSlot; this.stack = stack; this.maxAmount = maxAmount; this.alternativesScreenFactory = alternativesScreenFactory; } @Override protected int getOkCancelButtonWidth() { return alternativesScreenFactory != null ? 75 : super.getOkCancelButtonWidth(); } @Override public void onPostInit(int x, int y) { super.onPostInit(x, y); if (alternativesScreenFactory != null) { addButton(x + 114, cancelButton.getY() + 24, getOkCancelButtonWidth(), 20, Component.translatable("gui.refinedstorage.alternatives"), true, true, btn -> minecraft.setScreen(alternativesScreenFactory.apply(this))); } } @Override protected Pair getOkCancelPos() { if (alternativesScreenFactory == null) { return super.getOkCancelPos(); } return Pair.of(114, 22); } @Override protected int getDefaultAmount() { return stack.getCount(); } @Override protected boolean canAmountGoNegative() { return false; } @Override protected int getMaxAmount() { return maxAmount; } @Override protected Component getOkButtonText() { return Component.translatable("misc.refinedstorage.set"); } @Override protected ResourceLocation getTexture() { return alternativesScreenFactory != null ? TEXTURE_WIDE : TEXTURE; } @Override protected int[] getIncrements() { return new int[]{ 1, 10, 64, -1, -10, -64 }; } @Override protected void onOkButtonPressed(boolean shiftDown) { try { int amount = Integer.parseInt(amountField.getValue()); RS.NETWORK_HANDLER.sendToServer(new SetFilterSlotMessage(containerSlot, ItemHandlerHelper.copyStackWithSize(stack, amount))); close(); } catch (NumberFormatException e) { // NO OP } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/KeyInputListener.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.RSKeyBindings; import com.refinedmods.refinedstorage.integration.curios.CuriosIntegration; import com.refinedmods.refinedstorage.inventory.player.PlayerSlot; import com.refinedmods.refinedstorage.network.OpenNetworkItemMessage; import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.world.Container; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.client.event.InputEvent; import org.apache.commons.lang3.tuple.ImmutableTriple; import top.theillusivec4.curios.api.CuriosApi; import java.util.Arrays; import java.util.HashSet; import java.util.Optional; import java.util.Set; public class KeyInputListener { //These are static to be accessible from RSAddons public static void findAndOpen(Item... items) { Set validItems = new HashSet<>(Arrays.asList(items)); Container inv = Minecraft.getInstance().player.getInventory(); int slotFound = -1; for (int i = 0; i < inv.getContainerSize(); ++i) { ItemStack slot = inv.getItem(i); if (validItems.contains(slot.getItem())) { if (slotFound != -1) { sendError(Component.translatable("misc.refinedstorage.network_item.shortcut_duplicate", Component.translatable(items[0].getDescriptionId()))); return; } slotFound = i; } } if (CuriosIntegration.isLoaded() && slotFound == -1) { Optional> curio = CuriosApi.getCuriosHelper().findEquippedCurio(stack -> validItems.contains(stack.getItem()), Minecraft.getInstance().player); if (curio.isPresent()) { RS.NETWORK_HANDLER.sendToServer(new OpenNetworkItemMessage(new PlayerSlot(curio.get().getMiddle(), curio.get().getLeft()))); return; } } if (slotFound == -1) { sendError(Component.translatable("misc.refinedstorage.network_item.shortcut_not_found", Component.translatable(items[0].getDescriptionId()))); } else { RS.NETWORK_HANDLER.sendToServer(new OpenNetworkItemMessage(new PlayerSlot(slotFound))); } } public static void sendError(MutableComponent error) { Minecraft.getInstance().player.sendSystemMessage(error); } @SubscribeEvent public void onKeyInput(InputEvent.Key e) { if (Minecraft.getInstance().player != null) { if (RSKeyBindings.OPEN_WIRELESS_GRID.isDown()) { findAndOpen(RSItems.WIRELESS_GRID.get(), RSItems.CREATIVE_WIRELESS_GRID.get()); } else if (RSKeyBindings.OPEN_WIRELESS_FLUID_GRID.isDown()) { findAndOpen(RSItems.WIRELESS_FLUID_GRID.get(), RSItems.CREATIVE_WIRELESS_FLUID_GRID.get()); } else if (RSKeyBindings.OPEN_PORTABLE_GRID.isDown()) { findAndOpen(RSItems.PORTABLE_GRID.get(), RSItems.CREATIVE_PORTABLE_GRID.get()); } else if (RSKeyBindings.OPEN_WIRELESS_CRAFTING_MONITOR.isDown()) { findAndOpen(RSItems.WIRELESS_CRAFTING_MONITOR.get(), RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR.get()); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/NetworkTransmitterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.NetworkTransmitterBlockEntity; import com.refinedmods.refinedstorage.container.NetworkTransmitterContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import java.util.Optional; public class NetworkTransmitterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/network_transmitter.png"); public NetworkTransmitterScreen(NetworkTransmitterContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); String text; Optional receiverDim = NetworkTransmitterBlockEntity.RECEIVER_DIMENSION.getValue(); int distance = NetworkTransmitterBlockEntity.DISTANCE.getValue(); if (!receiverDim.isPresent()) { text = I18n.get("gui.refinedstorage.network_transmitter.missing_card"); } else if (distance != -1) { text = I18n.get("gui.refinedstorage.network_transmitter.distance", distance); } else { text = receiverDim.get().toString(); } renderString(graphics, 51, 24, text); renderString(graphics, 7, 42, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/PriorityScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import org.apache.commons.lang3.tuple.Pair; public class PriorityScreen extends AmountSpecifyingScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/priority.png"); private final BlockEntitySynchronizationParameter priority; public PriorityScreen(BaseScreen parent, BlockEntitySynchronizationParameter priority, Inventory inventory) { super(parent, new AbstractContainerMenu(null, 0) { @Override public ItemStack quickMoveStack(Player p_38941_, int p_38942_) { return ItemStack.EMPTY; } @Override public boolean stillValid(Player player) { return false; } }, 164, 92, inventory, Component.translatable("misc.refinedstorage.priority")); this.priority = priority; } @Override protected int getDefaultAmount() { return priority.getValue(); } @Override protected Component getOkButtonText() { return Component.translatable("misc.refinedstorage.set"); } @Override protected ResourceLocation getTexture() { return TEXTURE; } @Override protected Pair getAmountPos() { return Pair.of(18 + 1, 47 + 1); } @Override protected Pair getOkCancelPos() { return Pair.of(107, 30); } @Override protected boolean canAmountGoNegative() { return true; } @Override protected int getMaxAmount() { return Integer.MAX_VALUE; } @Override protected int[] getIncrements() { return new int[]{ 1, 5, 10, -1, -5, -10 }; } @Override protected void onOkButtonPressed(boolean noPreview) { try { int amount = Integer.parseInt(amountField.getValue()); BlockEntitySynchronizationManager.setParameter(priority, amount); close(); } catch (NumberFormatException e) { // NO OP } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/RelayScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.container.RelayContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class RelayScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/relay.png"); public RelayScreen(RelayContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 131, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 39, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/SecurityManagerScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.SecurityManagerBlockEntity; import com.refinedmods.refinedstorage.container.SecurityManagerContainerMenu; import com.refinedmods.refinedstorage.item.SecurityCardItem; import com.refinedmods.refinedstorage.network.SecurityManagerUpdateMessage; import com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; public class SecurityManagerScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/security_manager.png"); private final SecurityManagerBlockEntity securityManager; private final SmallCheckboxWidget[] permissions = new SmallCheckboxWidget[Permission.values().length]; public SecurityManagerScreen(SecurityManagerContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 176, 234, inventory, title); this.securityManager = (SecurityManagerBlockEntity) containerMenu.getBlockEntity(); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); int padding = 15; permissions[0] = addCheckBox(x + 7, y + 93, Component.translatable("gui.refinedstorage.security_manager.permission.0"), false, btn -> handle(0)); permissions[1] = addCheckBox(permissions[0].getX(), permissions[0].getY() + padding, Component.translatable("gui.refinedstorage.security_manager.permission.1"), false, btn -> handle(1)); permissions[2] = addCheckBox(permissions[1].getX(), permissions[1].getY() + padding, Component.translatable("gui.refinedstorage.security_manager.permission.2"), false, btn -> handle(2)); permissions[3] = addCheckBox(permissions[0].getX() + 90, permissions[0].getY(), Component.translatable("gui.refinedstorage.security_manager.permission.3"), false, btn -> handle(3)); permissions[4] = addCheckBox(permissions[3].getX(), permissions[3].getY() + padding, Component.translatable("gui.refinedstorage.security_manager.permission.4"), false, btn -> handle(4)); permissions[5] = addCheckBox(permissions[4].getX(), permissions[4].getY() + padding, Component.translatable("gui.refinedstorage.security_manager.permission.5"), false, btn -> handle(5)); } private void handle(int i) { RS.NETWORK_HANDLER.sendToServer(new SecurityManagerUpdateMessage(Permission.values()[i], permissions[i].isSelected())); } @Override public void tick(int x, int y) { ItemStack card = securityManager.getNode().getEditCard().getStackInSlot(0); for (Permission permission : Permission.values()) { permissions[permission.getId()].setSelected(!card.isEmpty() && SecurityCardItem.hasPermission(card, permission)); } } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 59, I18n.get("gui.refinedstorage.security_manager.configure")); renderString(graphics, 7, 140, I18n.get("container.inventory")); for (int i = 0; i < permissions.length; ++i) { SmallCheckboxWidget permission = permissions[i]; if (RenderUtils.inBounds(permission.getX() - leftPos, permission.getY() - topPos, permission.getWidth(), permission.getHeight(), mouseX, mouseY)) { renderTooltip(graphics, mouseX, mouseY, I18n.get("gui.refinedstorage.security_manager.permission." + i + ".tooltip")); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/StorageBlockScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.StorageBlockEntity; import com.refinedmods.refinedstorage.container.StorageContainerMenu; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class StorageBlockScreen extends StorageScreen { public StorageBlockScreen(StorageContainerMenu containerMenu, Inventory inventory, Component title) { super( containerMenu, inventory, title, new ResourceLocation(RS.ID, "textures/gui/storage.png"), new StorageScreenSynchronizationParameters( null, NetworkNodeBlockEntity.REDSTONE_MODE, StorageBlockEntity.COMPARE, StorageBlockEntity.WHITELIST_BLACKLIST, StorageBlockEntity.PRIORITY, StorageBlockEntity.ACCESS_TYPE ), StorageBlockEntity.STORED::getValue, () -> (long) ((StorageBlockEntity) containerMenu.getBlockEntity()).getItemStorageType().getCapacity() ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/StorageMonitorScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.StorageMonitorBlockEntity; import com.refinedmods.refinedstorage.container.StorageMonitorContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.ExactModeSideButton; import com.refinedmods.refinedstorage.screen.widget.sidebutton.TypeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class StorageMonitorScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/storage_monitor.png"); public StorageMonitorScreen(StorageMonitorContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new TypeSideButton(this, StorageMonitorBlockEntity.TYPE)); addSideButton(new ExactModeSideButton(this, StorageMonitorBlockEntity.COMPARE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/StorageScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.screen.widget.sidebutton.*; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu; import java.util.function.Supplier; public class StorageScreen extends BaseScreen { private static final int BAR_X = 8; private static final int BAR_Y = 54; private static final int BAR_WIDTH = 16; private static final int BAR_HEIGHT = 70; private final ResourceLocation texture; private final StorageScreenSynchronizationParameters parameters; private final Supplier storedSupplier; private final Supplier capacitySupplier; public StorageScreen(T containerMenu, Inventory inventory, Component title, ResourceLocation texture, StorageScreenSynchronizationParameters parameters, Supplier storedSupplier, Supplier capacitySupplier) { super(containerMenu, 176, 223, inventory, title); this.texture = texture; this.parameters = parameters; this.storedSupplier = storedSupplier; this.capacitySupplier = capacitySupplier; } @Override public void onPostInit(int x, int y) { if (parameters.getRedstoneModeParameter() != null) { addSideButton(new RedstoneModeSideButton(this, parameters.getRedstoneModeParameter())); } if (parameters.getTypeParameter() != null) { addSideButton(new TypeSideButton(this, parameters.getTypeParameter())); } if (parameters.getWhitelistBlacklistParameter() != null) { addSideButton(new WhitelistBlacklistSideButton(this, parameters.getWhitelistBlacklistParameter())); } if (parameters.getExactModeParameter() != null) { addSideButton(new ExactModeSideButton(this, parameters.getExactModeParameter())); } if (parameters.getAccessTypeParameter() != null) { addSideButton(new AccessTypeSideButton(this, parameters.getAccessTypeParameter())); } int buttonWidth = 10 + font.width(I18n.get("misc.refinedstorage.priority")); addButton( x + 169 - buttonWidth, y + 41, buttonWidth, 20, Component.translatable("misc.refinedstorage.priority"), true, true, btn -> minecraft.setScreen(new PriorityScreen(this, parameters.getPriorityParameter(), inventory)) ); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(texture, x, y, 0, 0, imageWidth, imageHeight); int barHeightNew = capacitySupplier.get() < 0 ? 0 : (int) ((float) storedSupplier.get() / (float) capacitySupplier.get() * (float) BAR_HEIGHT); graphics.blit(texture, x + BAR_X, y + BAR_Y + BAR_HEIGHT - barHeightNew, 179, BAR_HEIGHT - barHeightNew, BAR_WIDTH, barHeightNew); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, 42, capacitySupplier.get() == -1 ? I18n.get("misc.refinedstorage.storage.stored_minimal", API.instance().getQuantityFormatter().formatWithUnits(storedSupplier.get())) : I18n.get("misc.refinedstorage.storage.stored_capacity_minimal", API.instance().getQuantityFormatter().formatWithUnits(storedSupplier.get()), API.instance().getQuantityFormatter().formatWithUnits(capacitySupplier.get())) ); renderString(graphics, 7, 129, I18n.get("container.inventory")); if (RenderUtils.inBounds(BAR_X, BAR_Y, BAR_WIDTH, BAR_HEIGHT, mouseX, mouseY)) { int full = 0; if (capacitySupplier.get() >= 0) { full = (int) ((float) storedSupplier.get() / (float) capacitySupplier.get() * 100f); } renderTooltip(graphics, mouseX, mouseY, (capacitySupplier.get() == -1 ? I18n.get("misc.refinedstorage.storage.stored_minimal", API.instance().getQuantityFormatter().format(storedSupplier.get())) : I18n.get("misc.refinedstorage.storage.stored_capacity_minimal", API.instance().getQuantityFormatter().format(storedSupplier.get()), API.instance().getQuantityFormatter().format(capacitySupplier.get())) ) + "\n" + ChatFormatting.GRAY + I18n.get("misc.refinedstorage.storage.full", full)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/StorageScreenSynchronizationParameters.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import javax.annotation.Nullable; public class StorageScreenSynchronizationParameters { @Nullable private final BlockEntitySynchronizationParameter typeParameter; @Nullable private final BlockEntitySynchronizationParameter redstoneModeParameter; @Nullable private final BlockEntitySynchronizationParameter exactModeParameter; @Nullable private final BlockEntitySynchronizationParameter whitelistBlacklistParameter; private final BlockEntitySynchronizationParameter priorityParameter; @Nullable private final BlockEntitySynchronizationParameter accessTypeParameter; public StorageScreenSynchronizationParameters(@Nullable BlockEntitySynchronizationParameter typeParameter, @Nullable BlockEntitySynchronizationParameter redstoneModeParameter, @Nullable BlockEntitySynchronizationParameter exactModeParameter, @Nullable BlockEntitySynchronizationParameter whitelistBlacklistParameter, BlockEntitySynchronizationParameter priorityParameter, @Nullable BlockEntitySynchronizationParameter accessTypeParameter) { this.typeParameter = typeParameter; this.redstoneModeParameter = redstoneModeParameter; this.exactModeParameter = exactModeParameter; this.whitelistBlacklistParameter = whitelistBlacklistParameter; this.priorityParameter = priorityParameter; this.accessTypeParameter = accessTypeParameter; } @Nullable public BlockEntitySynchronizationParameter getTypeParameter() { return typeParameter; } @Nullable public BlockEntitySynchronizationParameter getRedstoneModeParameter() { return redstoneModeParameter; } @Nullable public BlockEntitySynchronizationParameter getExactModeParameter() { return exactModeParameter; } @Nullable public BlockEntitySynchronizationParameter getWhitelistBlacklistParameter() { return whitelistBlacklistParameter; } public BlockEntitySynchronizationParameter getPriorityParameter() { return priorityParameter; } @Nullable public BlockEntitySynchronizationParameter getAccessTypeParameter() { return accessTypeParameter; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/WirelessTransmitterScreen.java ================================================ package com.refinedmods.refinedstorage.screen; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.WirelessTransmitterBlockEntity; import com.refinedmods.refinedstorage.container.WirelessTransmitterContainerMenu; import com.refinedmods.refinedstorage.screen.widget.sidebutton.RedstoneModeSideButton; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; public class WirelessTransmitterScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/wireless_transmitter.png"); public WirelessTransmitterScreen(WirelessTransmitterContainerMenu containerMenu, Inventory inventory, Component title) { super(containerMenu, 211, 137, inventory, title); } @Override public void onPostInit(int x, int y) { addSideButton(new RedstoneModeSideButton(this, NetworkNodeBlockEntity.REDSTONE_MODE)); } @Override public void tick(int x, int y) { // NO OP } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 28, 25, I18n.get("gui.refinedstorage.wireless_transmitter.distance", WirelessTransmitterBlockEntity.RANGE.getValue())); renderString(graphics, 7, 43, I18n.get("container.inventory")); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/factory/CrafterManagerScreenFactory.java ================================================ package com.refinedmods.refinedstorage.screen.factory; import com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu; import com.refinedmods.refinedstorage.screen.CrafterManagerScreen; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; public class CrafterManagerScreenFactory implements MenuScreens.ScreenConstructor { @Override public CrafterManagerScreen create(CrafterManagerContainerMenu container, Inventory playerInventory, Component title) { CrafterManagerScreen screen = new CrafterManagerScreen(container, playerInventory, title); container.setScreenInfoProvider(screen); return screen; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/factory/GridScreenFactory.java ================================================ package com.refinedmods.refinedstorage.screen.factory; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; public class GridScreenFactory implements MenuScreens.ScreenConstructor { @Override public GridScreen create(GridContainerMenu container, Inventory inv, Component title) { GridScreen screen = new GridScreen(container, container.getGrid(), inv, title); container.setScreenInfoProvider(screen); return screen; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/AlternativesScreen.java ================================================ package com.refinedmods.refinedstorage.screen.grid; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.container.AlternativesContainerMenu; import com.refinedmods.refinedstorage.render.FluidRenderer; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.material.Fluid; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import org.lwjgl.glfw.GLFW; import java.util.*; import java.util.stream.Collectors; public class AlternativesScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/alternatives.png"); private static final int VISIBLE_ROWS = 5; private final Screen parent; private final ScrollbarWidget scrollbar; private final List lines = new ArrayList<>(); private int type; private int slot; private ItemStack item; private FluidStack fluid; private AlternativesScreen(Screen parent, Player player, Component title) { super(new AlternativesContainerMenu(player), 175, 143, player.getInventory(), title); this.parent = parent; this.scrollbar = new ScrollbarWidget(this, 155, 20, 12, 89); } public AlternativesScreen(Screen parent, Player player, Component title, ItemStack item, int slot) { this(parent, player, title); this.type = IType.ITEMS; this.slot = slot; this.item = item; this.fluid = null; } public AlternativesScreen(Screen parent, Player player, Component title, FluidStack fluid, int slot) { this(parent, player, title); this.type = IType.FLUIDS; this.slot = slot; this.item = null; this.fluid = fluid; } @Override public void onPostInit(int x, int y) { lines.clear(); if (item != null) { lines.add(new ItemLine(item)); Collection> tagsOfItem = BuiltInRegistries.ITEM.getResourceKey(item.getItem()) .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k) .map(holder -> holder.tags().collect(Collectors.toSet()))) .orElse(Collections.emptySet()); for (TagKey owningTag : tagsOfItem) { lines.add(new TagLine(owningTag.location(), GridBlockEntity.ALLOWED_ITEM_TAGS.getValue().get(slot).contains(owningTag.location()))); int itemCount = 0; ItemListLine line = new ItemListLine(); for (Holder itemInTag : BuiltInRegistries.ITEM.getTagOrEmpty(owningTag)) { if (itemCount > 0 && itemCount % 8 == 0) { lines.add(line); line = new ItemListLine(); } itemCount++; line.addItem(new ItemStack(itemInTag)); } lines.add(line); } } else if (fluid != null) { lines.add(new FluidLine(fluid)); Collection> tagsOfFluid = BuiltInRegistries.FLUID.getResourceKey(fluid.getFluid()) .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k) .map(holder -> holder.tags().collect(Collectors.toSet()))) .orElse(Collections.emptySet()); for (TagKey owningTag : tagsOfFluid) { lines.add(new TagLine(owningTag.location(), GridBlockEntity.ALLOWED_FLUID_TAGS.getValue().get(slot).contains(owningTag.location()))); int fluidCount = 0; FluidListLine line = new FluidListLine(); for (Holder fluidInTag : BuiltInRegistries.FLUID.getTagOrEmpty(owningTag)) { if (fluidCount > 0 && fluidCount % 8 == 0) { lines.add(line); line = new FluidListLine(); } fluidCount++; line.addFluid(new FluidStack(fluidInTag, FluidType.BUCKET_VOLUME)); } lines.add(line); } } // Do an initial layout int xx = 8; int yy = 20; for (int i = 0; i < lines.size(); ++i) { boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS; if (visible) { lines.get(i).layoutDependantControls(true, leftPos + xx + 3, topPos + yy + 3); yy += 18; } } Button apply = addButton(x + 7, y + 114, 50, 20, Component.translatable("gui.refinedstorage.alternatives.apply"), lines.size() > 1, true, btn -> apply()); addButton(x + apply.getWidth() + 7 + 4, y + 114, 50, 20, Component.translatable("gui.cancel"), true, true, btn -> close()); } @Override public void tick(int x, int y) { scrollbar.setEnabled(getRows() > VISIBLE_ROWS); scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS); } private int getRows() { return lines.size(); } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); scrollbar.render(graphics); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); int x = 8; int y = 20; for (int i = 0; i < lines.size(); ++i) { boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS; if (visible) { lines.get(i).layoutDependantControls(true, leftPos + x + 3, topPos + y + 3); lines.get(i).render(graphics, x, y); y += 18; } else { lines.get(i).layoutDependantControls(false, -100, -100); } } x = 8; y = 20; for (int i = 0; i < lines.size(); ++i) { boolean visible = i >= scrollbar.getOffset() && i < scrollbar.getOffset() + VISIBLE_ROWS; if (visible) { lines.get(i).renderTooltip(graphics, x, y, mouseX, mouseY); y += 18; } } } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); super.mouseMoved(mx, my); } @Override public boolean mouseClicked(double mx, double my, int button) { return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button); } @Override public boolean mouseReleased(double mx, double my, int button) { return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (key == GLFW.GLFW_KEY_ESCAPE) { close(); return true; } return super.keyPressed(key, scanCode, modifiers); } private void close() { minecraft.setScreen(parent); } private void apply() { Set allowed = new HashSet<>(); for (Line line : lines) { if (line instanceof TagLine) { TagLine tagLine = (TagLine) line; if (tagLine.widget.isSelected()) { allowed.add(tagLine.tagName); } } } if (type == IType.ITEMS) { List> existing = GridBlockEntity.ALLOWED_ITEM_TAGS.getValue(); existing.set(slot, allowed); BlockEntitySynchronizationManager.setParameter(GridBlockEntity.ALLOWED_ITEM_TAGS, existing); } else if (type == IType.FLUIDS) { List> existing = GridBlockEntity.ALLOWED_FLUID_TAGS.getValue(); existing.set(slot, allowed); BlockEntitySynchronizationManager.setParameter(GridBlockEntity.ALLOWED_FLUID_TAGS, existing); } close(); } private interface Line { default void render(GuiGraphics graphics, int x, int y) { } default void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) { } default void layoutDependantControls(boolean visible, int x, int y) { } } private class ItemLine implements Line { private final ItemStack item; public ItemLine(ItemStack item) { this.item = item; } @Override public void render(GuiGraphics graphics, int x, int y) { RenderSystem.setShaderColor(1, 1, 1, 1); renderItem(graphics, x + 3, y + 2, item); renderString(graphics, x + 4 + 19, y + 7, item.getHoverName().getString()); } } private class FluidLine implements Line { private final FluidStack fluid; public FluidLine(FluidStack item) { this.fluid = item; } @Override public void render(GuiGraphics graphics, int x, int y) { FluidRenderer.INSTANCE.render(graphics, x + 3, y + 2, fluid); renderString(graphics, x + 4 + 19, y + 7, fluid.getDisplayName().getString()); } } private class TagLine implements Line { private final ResourceLocation tagName; private final SmallCheckboxWidget widget; public TagLine(ResourceLocation tagName, boolean checked) { this.tagName = tagName; this.widget = addCheckBox(-100, -100, Component.literal(RenderUtils.shorten(tagName.toString(), 22)), checked, btn -> { // NO OP }); widget.setFGColor(0xFF373737); widget.setShadow(false); } @Override public void layoutDependantControls(boolean visible, int x, int y) { widget.visible = visible; widget.setX(x); widget.setY(y); } } private class ItemListLine implements Line { private final List items = new ArrayList<>(); public void addItem(ItemStack stack) { items.add(stack); } @Override public void render(GuiGraphics graphics, int x, int y) { for (ItemStack itemInList : items) { renderItem(graphics, x + 3, y, itemInList); x += 17; } } @Override public void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) { for (ItemStack itemInList : items) { if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) { AlternativesScreen.this.renderTooltip(graphics, itemInList, mx, my, RenderUtils.getTooltipFromItem(itemInList)); } x += 17; } } } private class FluidListLine implements Line { private final List fluids = new ArrayList<>(); public void addFluid(FluidStack stack) { fluids.add(stack); } @Override public void render(GuiGraphics graphics, int x, int y) { for (FluidStack fluidInList : fluids) { FluidRenderer.INSTANCE.render(graphics, x + 3, y, fluidInList); x += 17; } } @Override public void renderTooltip(GuiGraphics graphics, int x, int y, int mx, int my) { for (FluidStack fluidInList : fluids) { if (RenderUtils.inBounds(x + 3, y, 16, 16, mx, my)) { AlternativesScreen.this.renderTooltip(graphics, mx, my, fluidInList.getDisplayName().getString()); } x += 17; } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/CraftingPreviewScreen.java ================================================ package com.refinedmods.refinedstorage.screen.grid; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.api.autocrafting.ICraftingPattern; import com.refinedmods.refinedstorage.api.autocrafting.preview.ICraftingPreviewElement; import com.refinedmods.refinedstorage.api.render.IElementDrawers; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.render.CraftingPreviewElementDrawers; import com.refinedmods.refinedstorage.item.PatternItem; import com.refinedmods.refinedstorage.network.grid.GridCraftingStartRequestMessage; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.resources.language.I18n; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.neoforged.neoforge.fluids.FluidStack; import org.lwjgl.glfw.GLFW; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; import java.util.UUID; public class CraftingPreviewScreen extends BaseScreen { private static final ResourceLocation TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafting_preview.png"); private static final int VISIBLE_ROWS = 5; private final List elements; private final Screen parent; private final ScrollbarWidget scrollbar; private final UUID id; private final int quantity; private final boolean fluids; private final IElementDrawers drawers = new CraftingPreviewElementDrawers(this); private ItemStack hoveringStack; private FluidStack hoveringFluid; public CraftingPreviewScreen(Screen parent, List elements, UUID id, int quantity, boolean fluids, Component title, Inventory inventory) { super(new AbstractContainerMenu(null, 0) { @Override public ItemStack quickMoveStack(Player p_38941_, int p_38942_) { return ItemStack.EMPTY; } @Override public boolean stillValid(@Nonnull Player player) { return false; } }, 254, 201, inventory, title); this.elements = new ArrayList<>(elements); this.parent = parent; this.id = id; this.quantity = quantity; this.fluids = fluids; this.scrollbar = new ScrollbarWidget(this, 235, 20, 12, 149); } @Override public void onPostInit(int x, int y) { addButton(x + 55, y + 201 - 20 - 7, 50, 20, Component.translatable("gui.cancel"), true, true, btn -> close()); Button startButton = addButton(x + 129, y + 201 - 20 - 7, 50, 20, Component.translatable("misc.refinedstorage.start"), true, true, btn -> startRequest()); startButton.active = elements.stream().noneMatch(ICraftingPreviewElement::doesDisableTaskStarting); } @Override public void tick(int x, int y) { scrollbar.setEnabled(getRows() > VISIBLE_ROWS); scrollbar.setMaxOffset(getRows() - VISIBLE_ROWS); } @Nullable private ErrorCraftingPreviewElement getError() { if (elements.size() == 1 && elements.get(0) instanceof ErrorCraftingPreviewElement) { return (ErrorCraftingPreviewElement) elements.get(0); } return null; } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { graphics.blit(TEXTURE, x, y, 0, 0, imageWidth, imageHeight); if (getError() != null) { graphics.fill(x + 7, y + 20, x + 228, y + 169, 0xFFDBDBDB); } scrollbar.render(graphics); } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); int x = 7; int y = 15; float scale = Minecraft.getInstance().isEnforceUnicode() ? 1F : 0.5F; ErrorCraftingPreviewElement error = getError(); if (error != null) { renderError(graphics, x, y, scale, error); } else { renderPreview(graphics, mouseX, mouseY, x, y); } } private void renderPreview(GuiGraphics graphics, int mouseX, int mouseY, int x, int y) { int slot = scrollbar != null ? (scrollbar.getOffset() * 3) : 0; Lighting.setupFor3DItems(); RenderSystem.enableDepthTest(); this.hoveringStack = null; this.hoveringFluid = null; for (int i = 0; i < 3 * 5; ++i) { if (slot < elements.size()) { renderElement(graphics, mouseX, mouseY, x, y, elements.get(slot)); } if ((i + 1) % 3 == 0) { x = 7; y += 30; } else { x += 74; } slot++; } } private void renderElement(GuiGraphics graphics, int mouseX, int mouseY, int x, int y, ICraftingPreviewElement element) { element.draw(graphics, x, y + 5, drawers); if (RenderUtils.inBounds(x + 5, y + 7, 16, 16, mouseX, mouseY)) { this.hoveringStack = element instanceof ItemCraftingPreviewElement ? ((ItemCraftingPreviewElement) element).getStack() : null; if (this.hoveringStack == null) { this.hoveringFluid = element instanceof FluidCraftingPreviewElement ? ((FluidCraftingPreviewElement) element).getStack() : null; } } } private void renderError(GuiGraphics graphics, int x, int y, float scale, ErrorCraftingPreviewElement errorElement) { final PoseStack poseStack = graphics.pose(); poseStack.pushPose(); poseStack.scale(scale, scale, 1); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 11, scale), I18n.get("gui.refinedstorage.crafting_preview.error")); switch (errorElement.getType()) { case RECURSIVE: renderRecursiveError(graphics, x, y, scale, errorElement.getRecursedPattern()); break; case TOO_COMPLEX: renderTooComplexError(graphics, x, y, scale); break; default: break; } poseStack.popPose(); } private void renderTooComplexError(GuiGraphics graphics, int x, int y, float scale) { renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), I18n.get("gui.refinedstorage.crafting_preview.error.too_complex.0")); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), I18n.get("gui.refinedstorage.crafting_preview.error.too_complex.1")); } private void renderRecursiveError(GuiGraphics graphics, int x, int y, float scale, ItemStack recursedPattern) { renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 21, scale), I18n.get("gui.refinedstorage.crafting_preview.error.recursive.0")); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 31, scale), I18n.get("gui.refinedstorage.crafting_preview.error.recursive.1")); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 41, scale), I18n.get("gui.refinedstorage.crafting_preview.error.recursive.2")); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 51, scale), I18n.get("gui.refinedstorage.crafting_preview.error.recursive.3")); renderString(graphics, RenderUtils.getOffsetOnScale(x + 5, scale), RenderUtils.getOffsetOnScale(y + 61, scale), I18n.get("gui.refinedstorage.crafting_preview.error.recursive.4")); ICraftingPattern pattern = PatternItem.fromCache(parent.getMinecraft().level, recursedPattern); int yy = 83; for (ItemStack output : pattern.getOutputs()) { if (output != null) { renderString(graphics, RenderUtils.getOffsetOnScale(x + 25, scale), RenderUtils.getOffsetOnScale(yy + 6, scale), output.getHoverName().getString()); Lighting.setupFor3DItems(); RenderSystem.enableDepthTest(); renderItem(graphics, x + 5, yy, output); yy += 17; } } } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { super.render(graphics, mouseX, mouseY, partialTicks); if (hoveringStack != null) { renderTooltip( graphics, hoveringStack, mouseX, mouseY, hoveringStack.getTooltipLines( Minecraft.getInstance().player, Minecraft.getInstance().options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL ) ); } else if (hoveringFluid != null) { renderTooltip(graphics, mouseX, mouseY, hoveringFluid.getDisplayName().getString()); } } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); super.mouseMoved(mx, my); } @Override public boolean mouseClicked(double mx, double my, int button) { return scrollbar.mouseClicked(mx, my, button) || super.mouseClicked(mx, my, button); } @Override public boolean mouseReleased(double mx, double my, int button) { return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (key == GLFW.GLFW_KEY_ENTER || key == GLFW.GLFW_KEY_KP_ENTER) { startRequest(); return true; } if (key == GLFW.GLFW_KEY_ESCAPE) { close(); return true; } return super.keyPressed(key, scanCode, modifiers); } private void startRequest() { RS.NETWORK_HANDLER.sendToServer(new GridCraftingStartRequestMessage(id, quantity, fluids)); close(); } private int getRows() { return Math.max(0, (int) Math.ceil((float) elements.size() / 3F)); } private void close() { minecraft.setScreen(parent); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/CraftingSettingsScreen.java ================================================ package com.refinedmods.refinedstorage.screen.grid; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.container.CraftingSettingsContainerMenu; import com.refinedmods.refinedstorage.network.grid.GridCraftingPreviewRequestMessage; import com.refinedmods.refinedstorage.screen.AmountSpecifyingScreen; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Player; import net.neoforged.neoforge.fluids.FluidType; public class CraftingSettingsScreen extends AmountSpecifyingScreen { private final IGridStack stack; public CraftingSettingsScreen(BaseScreen parent, Player player, IGridStack stack) { super(parent, new CraftingSettingsContainerMenu(player, stack), 172, 99, player.getInventory(), Component.translatable("container.crafting")); this.stack = stack; } @Override protected Component getOkButtonText() { return Component.translatable("misc.refinedstorage.start"); } @Override protected int[] getIncrements() { if (stack instanceof FluidGridStack) { return new int[]{ 100, 500, 1000, -100, -500, -1000 }; } else { return new int[]{ 1, 10, 64, -1, -10, -64 }; } } @Override protected int getDefaultAmount() { return stack instanceof FluidGridStack ? FluidType.BUCKET_VOLUME : 1; } @Override protected boolean canAmountGoNegative() { return false; } @Override protected int getMaxAmount() { return Integer.MAX_VALUE; } @Override protected void onOkButtonPressed(boolean shiftDown) { try { int quantity = Integer.parseInt(amountField.getValue()); RS.NETWORK_HANDLER.sendToServer(new GridCraftingPreviewRequestMessage(stack.getId(), quantity, shiftDown, stack instanceof FluidGridStack)); okButton.active = false; } catch (NumberFormatException e) { // NO OP } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/GridScreen.java ================================================ package com.refinedmods.refinedstorage.screen.grid; import com.mojang.blaze3d.platform.Lighting; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSKeyBindings; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.network.grid.handler.IItemGridHandler; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers; import com.refinedmods.refinedstorage.blockentity.NetworkNodeBlockEntity; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.grid.GridBlockEntity; import com.refinedmods.refinedstorage.blockentity.grid.portable.IPortableGrid; import com.refinedmods.refinedstorage.blockentity.grid.portable.PortableGridBlockEntity; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.network.grid.*; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.IScreenInfoProvider; import com.refinedmods.refinedstorage.screen.grid.sorting.*; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import com.refinedmods.refinedstorage.screen.grid.view.GridViewImpl; import com.refinedmods.refinedstorage.screen.grid.view.IGridView; import com.refinedmods.refinedstorage.screen.widget.SmallCheckboxWidget; import com.refinedmods.refinedstorage.screen.widget.ScrollbarWidget; import com.refinedmods.refinedstorage.screen.widget.SearchWidget; import com.refinedmods.refinedstorage.screen.widget.TabListWidget; import com.refinedmods.refinedstorage.screen.widget.sidebutton.*; import com.refinedmods.refinedstorage.util.RenderUtils; import com.refinedmods.refinedstorage.util.TimeUtils; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.client.gui.screens.inventory.tooltip.DefaultTooltipPositioner; import net.minecraft.client.resources.language.I18n; import net.minecraft.client.resources.sounds.SimpleSoundInstance; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.FormattedText; import net.minecraft.network.chat.MutableComponent; import net.minecraft.resources.ResourceLocation; import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.client.ClientHooks; import org.lwjgl.glfw.GLFW; import yalter.mousetweaks.api.MouseTweaksDisableWheelTweak; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; @MouseTweaksDisableWheelTweak public class GridScreen extends BaseScreen implements IScreenInfoProvider { private static final ResourceLocation PORTABLE_GRID_TEXTURE = new ResourceLocation(RS.ID, "textures/gui/portable_grid.png"); private static final ResourceLocation CRAFTING_GRID_TEXTURE = new ResourceLocation(RS.ID, "textures/gui/crafting_grid.png"); private static final ResourceLocation PATTERN_GRID_TEXTURE = new ResourceLocation(RS.ID, "textures/gui/pattern_grid.png"); private static final ResourceLocation PATTERN_GRID_PROCESSING_TEXTURE = new ResourceLocation(RS.ID, "textures/gui/pattern_grid_processing.png"); private static final ResourceLocation GRID_TEXTURE = new ResourceLocation(RS.ID, "textures/gui/grid.png"); private static String searchQuery = ""; private final IGrid grid; private final TabListWidget tabs; private final int patternScrollOffsetAbsoluteMax = GridNetworkNode.PROCESSING_MATRIX_SIZE / 3 - 3; private IGridView view; private SearchWidget searchField; private SmallCheckboxWidget exactPattern; private SmallCheckboxWidget processingPattern; private SmallCheckboxWidget fluidCheckBox; private ScrollbarWidget scrollbar; private ScrollbarWidget patternScrollbar; private boolean wasConnected; private boolean doSort; private int slotNumber; private int slotNumberX; private int slotNumberY; private int patternScrollOffset; private int patternScrollOffsetMax; private boolean updatePatternOffset; public GridScreen(GridContainerMenu containerMenu, IGrid grid, Inventory inventory, Component title) { super(containerMenu, 227, 0, inventory, title); this.grid = grid; this.view = new GridViewImpl(this, getDefaultSorter(), getSorters()); this.wasConnected = this.grid.isGridActive(); this.tabs = new TabListWidget<>(this, new ElementDrawers<>(this), grid::getTabs, grid::getTotalTabPages, grid::getTabPage, grid::getTabSelected, IGrid.TABS_PER_PAGE); this.tabs.addListener(new TabListWidget.ITabListListener() { @Override public void onSelectionChanged(int tab) { grid.onTabSelectionChanged(tab); } @Override public void onPageChanged(int page) { grid.onTabPageChanged(page); } }); if (grid instanceof GridNetworkNode && grid.getGridType() == GridType.PATTERN) { GridNetworkNode node = (GridNetworkNode) grid; node.getProcessingMatrix().addListener((handler, slot, reading) -> updatePatternOffset = true); node.getProcessingMatrixFluids().addListener((handler, slot, reading) -> updatePatternOffset = true); } } public static List getSorters() { List sorters = new LinkedList<>(); sorters.add(getDefaultSorter()); sorters.add(new QuantityGridSorter()); sorters.add(new IdGridSorter()); sorters.add(new LastModifiedGridSorter()); return sorters; } public static IGridSorter getDefaultSorter() { return new NameGridSorter(); } @Override protected void onPreInit() { super.onPreInit(); this.doSort = true; this.imageHeight = getTopHeight() + getBottomHeight() + (getVisibleRows() * 18); } @Override public void onPostInit(int x, int y) { this.menu.initSlots(); this.tabs.init(imageWidth - 32); this.scrollbar = new ScrollbarWidget(this, 174, getTopHeight(), 12, (getVisibleRows() * 18) - 2); if (grid instanceof GridNetworkNode || grid instanceof PortableGridBlockEntity) { addSideButton(new RedstoneModeSideButton(this, grid instanceof GridNetworkNode ? NetworkNodeBlockEntity.REDSTONE_MODE : PortableGridBlockEntity.REDSTONE_MODE)); } int sx = x + 80 + 1; int sy = y + 6 + 1; if (searchField == null) { searchField = new SearchWidget(font, sx, sy, 88 - 6); searchField.setResponder(value -> { searchField.updateJei(); getView().sort(); // Use getter since this view can be replaced. searchQuery = value; }); searchField.setMode(grid.getSearchBoxMode()); searchField.setValue(searchQuery); } else { searchField.setX(sx); searchField.setY(sy); } addRenderableWidget(searchField); if (searchField.isFocused()) { setFocused(searchField); } if (grid.getViewType() != -1) { addSideButton(new GridViewTypeSideButton(this, grid)); } addSideButton(new GridSortingDirectionSideButton(this, grid)); addSideButton(new GridSortingTypeSideButton(this, grid)); addSideButton(new GridSearchBoxModeSideButton(this)); addSideButton(new GridSizeSideButton(this, grid::getSize, grid::onSizeChanged)); if (grid.getGridType() == GridType.PATTERN) { patternScrollbar = new ScrollbarWidget(this, 160, getTopHeight() + getVisibleRows() * 18 + 4, 6, 18 * 3 - 2, true); patternScrollbar.setMaxOffset(patternScrollOffsetAbsoluteMax); patternScrollbar.setOffset(patternScrollOffset); // keep offset when changing between fluid and item view menu.updatePatternSlotPositions(patternScrollOffset); patternScrollbar.addListener((oldOffset, newOffset) -> { patternScrollOffset = newOffset; menu.updatePatternSlotPositions(newOffset); }); processingPattern = addCheckBox(x + 7, y + getTopHeight() + (getVisibleRows() * 18) + 60, Component.translatable("misc.refinedstorage.processing"), GridBlockEntity.PROCESSING_PATTERN.getValue(), btn -> { // Rebuild the inventory slots before the slot change packet arrives. GridBlockEntity.PROCESSING_PATTERN.setValue(false, processingPattern.isSelected()); ((GridNetworkNode) grid).clearMatrix(); // The server does this but let's do it earlier so the client doesn't notice. this.menu.initSlots(); patternScrollOffset = 0; // reset offset when switching between crafting and processing BlockEntitySynchronizationManager.setParameter(GridBlockEntity.PROCESSING_PATTERN, processingPattern.isSelected()); }); if (!processingPattern.isSelected()) { exactPattern = addCheckBox( processingPattern.getX() + processingPattern.getWidth() + 5, y + getTopHeight() + (getVisibleRows() * 18) + 60, Component.translatable("misc.refinedstorage.exact"), GridBlockEntity.EXACT_PATTERN.getValue(), btn -> BlockEntitySynchronizationManager.setParameter(GridBlockEntity.EXACT_PATTERN, exactPattern.isSelected()) ); patternScrollbar.setEnabled(false); } else { patternScrollbar.setEnabled(true); fluidCheckBox = addCheckBox(processingPattern.getX() + processingPattern.getWidth() + 5, y + getTopHeight() + (getVisibleRows() * 18) + 60, Component.translatable("misc.refinedstorage.fluidmode"), ((GridNetworkNode) grid).getType() == IType.FLUIDS, button -> { BlockEntitySynchronizationManager.setParameter(GridBlockEntity.PROCESSING_TYPE, GridBlockEntity.PROCESSING_TYPE.getValue() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS); }); } } updateScrollbar(); } public IGrid getGrid() { return grid; } public IGridView getView() { return view; } public void setView(IGridView view) { this.view = view; } @Override public void tick(int x, int y) { if (wasConnected != grid.isGridActive()) { wasConnected = grid.isGridActive(); view.sort(); } if (updatePatternOffset) { updatePatternOffsetMax(); updatePatternOffset = false; } if (isKeyDown(RSKeyBindings.CLEAR_GRID_CRAFTING_MATRIX)) { RS.NETWORK_HANDLER.sendToServer(new GridClearMessage()); } tabs.update(); } @Override public int getTopHeight() { return 19; } @Override public int getBottomHeight() { if (grid.getGridType() == GridType.CRAFTING) { return 156; } else if (grid.getGridType() == GridType.PATTERN) { return 169; } else { return 99; } } @Override public int getYPlayerInventory() { int yp = getTopHeight() + (getVisibleRows() * 18); if (grid.getGridType() == GridType.NORMAL || grid.getGridType() == GridType.FLUID) { yp += 16; } else if (grid.getGridType() == GridType.CRAFTING) { yp += 73; } else if (grid.getGridType() == GridType.PATTERN) { yp += 86; } return yp; } @Override public int getRows() { return Math.max(0, (int) Math.ceil((float) view.getStacks().size() / 9F)); } @Override public int getCurrentOffset() { return scrollbar.getOffset(); } @Override public String getSearchFieldText() { return searchField.getValue(); } @Override public int getVisibleRows() { switch (grid.getSize()) { case IGrid.SIZE_STRETCH: int screenSpaceAvailable = height - getTopHeight() - getBottomHeight(); return Math.max(3, Math.min((screenSpaceAvailable / 18) - 3, RS.CLIENT_CONFIG.getGrid().getMaxRowsStretch())); case IGrid.SIZE_SMALL: return 3; case IGrid.SIZE_MEDIUM: return 5; case IGrid.SIZE_LARGE: return 8; default: return 3; } } private boolean isOverSlotWithStack() { return grid.isGridActive() && isOverSlot() && slotNumber < view.getStacks().size(); } private boolean isOverSlot() { return slotNumber >= 0; } public boolean isOverSlotArea(double mouseX, double mouseY) { return RenderUtils.inBounds(7, 19, 162, 18 * getVisibleRows(), mouseX, mouseY); } public int getSlotNumber() { return slotNumber; } public int getSlotNumberX() { return slotNumberX; } public int getSlotNumberY() { return slotNumberY; } private boolean isOverClear(double mouseX, double mouseY) { int y = getTopHeight() + (getVisibleRows() * 18) + 4; switch (grid.getGridType()) { case CRAFTING: return RenderUtils.inBounds(82, y, 7, 7, mouseX, mouseY); case PATTERN: if (((GridNetworkNode) grid).isProcessingPattern()) { return RenderUtils.inBounds(149, y, 7, 7, mouseX, mouseY); } return RenderUtils.inBounds(82, y, 7, 7, mouseX, mouseY); default: return false; } } private boolean isOverCreatePattern(double mouseX, double mouseY) { return grid.getGridType() == GridType.PATTERN && RenderUtils.inBounds(172, getTopHeight() + (getVisibleRows() * 18) + 22, 16, 16, mouseX, mouseY) && ((GridNetworkNode) grid).canCreatePattern(); } @Override public void renderBackground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY) { tabs.drawBackground(graphics, x, y - tabs.getHeight()); ResourceLocation texture; if (grid instanceof IPortableGrid) { texture = PORTABLE_GRID_TEXTURE; } else if (grid.getGridType() == GridType.CRAFTING) { texture = CRAFTING_GRID_TEXTURE; } else if (grid.getGridType() == GridType.PATTERN) { texture = ((GridNetworkNode) grid).isProcessingPattern() ? PATTERN_GRID_PROCESSING_TEXTURE : PATTERN_GRID_TEXTURE; } else { texture = GRID_TEXTURE; } int yy = y; graphics.blit(texture, x, yy, 0, 0, imageWidth - 34, getTopHeight()); // Filters and/or portable grid disk graphics.blit(texture, x + imageWidth - 34 + 4, y, 197, 0, 30, grid instanceof IPortableGrid ? 114 : 82); int rows = getVisibleRows(); for (int i = 0; i < rows; ++i) { yy += 18; int yTextureStart = getTopHeight(); if (i > 0) { if (i == rows - 1) { yTextureStart += 18 * 2; } else { yTextureStart += 18; } } graphics.blit(texture, x, yy, 0, yTextureStart, imageWidth - 34, 18); } yy += 18; graphics.blit(texture, x, yy, 0, getTopHeight() + (18 * 3), imageWidth - 34, getBottomHeight()); if (grid.getGridType() == GridType.PATTERN) { int ty = 0; if (isOverCreatePattern(mouseX - leftPos, mouseY - topPos)) { ty = 1; } if (!((GridNetworkNode) grid).canCreatePattern()) { ty = 2; } graphics.blit(texture, x + 172, y + getTopHeight() + (getVisibleRows() * 18) + 22, 240, ty * 16, 16, 16); if (processingPattern.isSelected()) { updatePatternScrollbar(); patternScrollbar.render(graphics); } } tabs.drawForeground(graphics, x, y - tabs.getHeight(), mouseX, mouseY, true); searchField.render(graphics, 0, 0, 0); scrollbar.render(graphics); } @Override public void render(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { super.render(graphics, mouseX, mouseY, partialTicks); // Drawn in here for bug #1844 (https://github.com/refinedmods/refinedstorage/issues/1844) // Item tooltips can't be rendered in the foreground layer due to the X offset translation. if (isOverSlotWithStack()) { drawGridTooltip(graphics, view.getStacks().get(slotNumber), mouseX, mouseY); } } @Override public void renderForeground(GuiGraphics graphics, int mouseX, int mouseY) { renderString(graphics, 7, 7, title.getString()); renderString(graphics, 7, getYPlayerInventory() - 12, I18n.get("container.inventory")); int x = 8; int y = 19; this.slotNumber = -1; this.slotNumberX = -1; this.slotNumberY = -1; int slot = scrollbar != null ? (scrollbar.getOffset() * 9) : 0; Lighting.setupFor3DItems(); for (int i = 0; i < 9 * getVisibleRows(); ++i) { if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) { this.slotNumber = slot; this.slotNumberX = x; this.slotNumberY = y; } if (slot < view.getStacks().size()) { view.getStacks().get(slot).draw(graphics, this, x, y); } if (RenderUtils.inBounds(x, y, 16, 16, mouseX, mouseY) || !grid.isGridActive()) { int color = grid.isGridActive() ? -2130706433 : 0xFF5B5B5B; graphics.pose().pushPose(); graphics.pose().translate(0, 0, 300); RenderSystem.disableDepthTest(); RenderSystem.colorMask(true, true, true, false); graphics.fillGradient(x, y, x + 16, y + 16, color, color); RenderSystem.colorMask(true, true, true, true); graphics.pose().popPose(); } slot++; x += 18; if ((i + 1) % 9 == 0) { x = 8; y += 18; } } if (isOverClear(mouseX, mouseY)) { renderTooltip(graphics, mouseX, mouseY, I18n.get("misc.refinedstorage.clear")); } if (isOverCreatePattern(mouseX, mouseY)) { renderTooltip(graphics, mouseX, mouseY, I18n.get("gui.refinedstorage.grid.pattern_create")); } tabs.drawTooltip(graphics, font, mouseX, mouseY); } private void drawGridTooltip(GuiGraphics graphics, IGridStack gridStack, int mouseX, int mouseY) { ItemStack stackContext = gridStack instanceof ItemGridStack ? ((ItemGridStack) gridStack).getStack() : ItemStack.EMPTY; List textElements = gridStack.getTooltip(true); List components = new ArrayList<>(ClientHooks.gatherTooltipComponents( stackContext, textElements, mouseX, minecraft.getWindow().getGuiScaledWidth(), minecraft.getWindow().getGuiScaledHeight(), font )); if (RS.CLIENT_CONFIG.getGrid().getDetailedTooltip()) { final float scale = (minecraft != null && minecraft.isEnforceUnicode()) ? 1F : 0.7F; if (!gridStack.isCraftable()) { MutableComponent total = Component.translatable("misc.refinedstorage.total", gridStack.getFormattedFullQuantity()) .withStyle(ChatFormatting.GRAY); components.add(new SmallClientTooltipComponent(total, scale)); } if (gridStack.getTrackerEntry() != null) { MutableComponent time = Component.translatable(TimeUtils.getAgo(gridStack.getTrackerEntry().getTime(), gridStack.getTrackerEntry().getName())) .withStyle(ChatFormatting.GRAY); components.add(new SmallClientTooltipComponent(time, scale)); } } graphics.renderTooltipInternal(font, components, mouseX, mouseY, DefaultTooltipPositioner.INSTANCE); } @Override public boolean mouseClicked(double mouseX, double mouseY, int clickedButton) { if (tabs.mouseClicked()) { setFocused(null); return true; } if (scrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { setFocused(null); return true; } if (grid.getGridType() == GridType.PATTERN && patternScrollbar.mouseClicked(mouseX, mouseY, clickedButton)) { setFocused(null); return true; } if (RS.CLIENT_CONFIG.getGrid().getPreventSortingWhileShiftIsDown()) { doSort = !isOverSlotArea(mouseX - leftPos, mouseY - topPos) && !isOverCraftingOutputArea(mouseX - leftPos, mouseY - topPos); } boolean clickedClear = clickedButton == 0 && isOverClear(mouseX - leftPos, mouseY - topPos); boolean clickedCreatePattern = clickedButton == 0 && isOverCreatePattern(mouseX - leftPos, mouseY - topPos); if (clickedCreatePattern) { minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); RS.NETWORK_HANDLER.sendToServer(new GridPatternCreateMessage(((GridNetworkNode) grid).getPos())); setFocused(null); return true; } else if (clickedClear) { minecraft.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F)); RS.NETWORK_HANDLER.sendToServer(new GridClearMessage()); setFocused(null); return true; } else if (grid.isGridActive()) { ItemStack held = menu.getCarried(); if (isOverSlotArea(mouseX - leftPos, mouseY - topPos) && !held.isEmpty() && (clickedButton == 0 || clickedButton == 1)) { if (grid.getGridType() == GridType.FLUID) { RS.NETWORK_HANDLER.sendToServer(new GridFluidInsertHeldMessage()); } else { RS.NETWORK_HANDLER.sendToServer(new GridItemInsertHeldMessage(clickedButton == 1)); } setFocused(null); return true; } if (isOverSlotWithStack()) { IGridStack stack = view.getStacks().get(slotNumber); if (held.isEmpty()) { if (view.canCraft() && stack.isCraftable()) { minecraft.setScreen(new CraftingSettingsScreen(this, inventory.player, stack)); } else if (view.canCraft() && !stack.isCraftable() && stack.getOtherId() != null && hasShiftDown() && hasControlDown()) { minecraft.setScreen(new CraftingSettingsScreen(this, inventory.player, view.get(stack.getOtherId()))); } else if (grid.getGridType() == GridType.FLUID && held.isEmpty()) { RS.NETWORK_HANDLER.sendToServer(new GridFluidPullMessage(view.getStacks().get(slotNumber).getId(), hasShiftDown())); } else if (grid.getGridType() != GridType.FLUID) { int flags = 0; if (clickedButton == 1) { flags |= IItemGridHandler.EXTRACT_HALF; } if (hasShiftDown()) { flags |= IItemGridHandler.EXTRACT_SHIFT; } RS.NETWORK_HANDLER.sendToServer(new GridItemPullMessage(stack.getId(), flags)); } } setFocused(null); return true; } } return super.mouseClicked(mouseX, mouseY, clickedButton); } private boolean isOverCraftingOutputArea(double mouseX, double mouseY) { if (grid.getGridType() != GridType.CRAFTING) { return false; } return RenderUtils.inBounds(130, getTopHeight() + getVisibleRows() * 18 + 18, 24, 24, mouseX, mouseY); } @Override public void mouseMoved(double mx, double my) { scrollbar.mouseMoved(mx, my); if (grid.getGridType() == GridType.PATTERN) { patternScrollbar.mouseMoved(mx, my); } super.mouseMoved(mx, my); } @Override public boolean mouseReleased(double mx, double my, int button) { if (grid.getGridType() == GridType.PATTERN && patternScrollbar.mouseReleased(mx, my, button)) { return true; } return scrollbar.mouseReleased(mx, my, button) || super.mouseReleased(mx, my, button); } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { if (hasShiftDown() || hasControlDown()) { if (RS.CLIENT_CONFIG.getGrid().getPreventSortingWhileShiftIsDown()) { doSort = !isOverSlotArea(x - leftPos, y - topPos) && !isOverCraftingOutputArea(x - leftPos, y - topPos); } if (grid.getGridType() != GridType.FLUID) { if (isOverInventory(x - leftPos, y - topPos) && hoveredSlot != null && hoveredSlot.hasItem() && getMenu().getDisabledSlotNumber() != hoveredSlot.getSlotIndex()) { RS.NETWORK_HANDLER.sendToServer(new GridItemInventoryScrollMessage(hoveredSlot.getSlotIndex(), hasShiftDown(), delta > 0)); } else if (isOverSlotArea(x - leftPos, y - topPos)) { RS.NETWORK_HANDLER.sendToServer(new GridItemGridScrollMessage(isOverSlotWithStack() ? view.getStacks().get(slotNumber).getId() : null, hasShiftDown(), delta > 0)); } } return super.mouseScrolled(x, y, z, delta); } if (grid.getGridType() == GridType.PATTERN && isOverPatternArea(x - leftPos, y - topPos) && patternScrollbar.mouseScrolled(x, y, z, delta)) { return true; } return this.scrollbar.mouseScrolled(x, y, z, delta) || super.mouseScrolled(x, y, z, delta); } private boolean isOverInventory(double x, double y) { return RenderUtils.inBounds(8, getYPlayerInventory(), 9 * 18 - 2, 4 * 18 + 2, x, y); } private boolean isOverPatternArea(double x, double y) { return RenderUtils.inBounds(8, getTopHeight() + getVisibleRows() * 18, 152, 54, x, y); } @Override public boolean charTyped(char unknown1, int unknown2) { if (searchField.charTyped(unknown1, unknown2)) { return true; } return super.charTyped(unknown1, unknown2); } @Override public boolean keyReleased(int keyCode, int scanCode, int modifiers) { if (keyCode == GLFW.GLFW_KEY_LEFT_SHIFT || keyCode == GLFW.GLFW_KEY_RIGHT_SHIFT || keyCode == GLFW.GLFW_KEY_LEFT_CONTROL || keyCode == GLFW.GLFW_KEY_RIGHT_CONTROL) { view.sort(); } return super.keyReleased(keyCode, scanCode, modifiers); } @Override public boolean keyPressed(int key, int scanCode, int modifiers) { if (searchField.keyPressed(key, scanCode, modifiers)) { return true; } return super.keyPressed(key, scanCode, modifiers); } @Override public void removed() { super.removed(); if (!RS.CLIENT_CONFIG.getGrid().getRememberSearchQuery()) { searchQuery = ""; } getView().removed(); } public SearchWidget getSearchField() { return searchField; } public void updateExactPattern(boolean checked) { if (exactPattern != null) { exactPattern.setSelected(checked); } } //check processing matrix and update maximum offset depending on contents private void updatePatternOffsetMax() { int filledInputSlots = 0; int filledOutputSlots = 0; int lastFilledInputSlot = 0; int lastFilledOutputSlot = 0; for (int i = 0; i < GridNetworkNode.PROCESSING_MATRIX_SIZE * 2; i++) { if (!isMatrixSlotEmpty(i)) { if (i > GridNetworkNode.PROCESSING_MATRIX_SIZE - 1) { filledOutputSlots++; lastFilledOutputSlot = i - GridNetworkNode.PROCESSING_MATRIX_SIZE - 1; } else { filledInputSlots++; lastFilledInputSlot = i; } } } int maxFilledSlots = Math.max(filledInputSlots, filledOutputSlots); int maxLastFilledSlot = Math.max(lastFilledInputSlot, lastFilledOutputSlot); // offset calculation to show next row if 4 of 9 slots are filled. int filledSlotOffset = Math.floorDiv(maxFilledSlots - 1, 3); // offset to show the last item in the matrix int lastSlotOffset = Math.floorDiv(maxLastFilledSlot, 3) - 2; patternScrollOffsetMax = Math.max(filledSlotOffset, lastSlotOffset); } private boolean isMatrixSlotEmpty(int slotNumber) { return ((GridNetworkNode) grid).getProcessingMatrix().getStackInSlot(slotNumber).isEmpty() && ((GridNetworkNode) grid).getProcessingMatrixFluids().getFluid(slotNumber).isEmpty(); } public void updatePatternScrollbar() { patternScrollbar.setEnabled(processingPattern.isSelected() && patternScrollOffsetMax > 0); int oldOffset = patternScrollbar.getOffset(); patternScrollbar.setMaxOffset(Math.min(patternScrollOffsetMax, patternScrollOffsetAbsoluteMax)); if (oldOffset != patternScrollbar.getOffset()) { menu.updatePatternSlotPositions(patternScrollbar.getOffset()); } } public void updateScrollbar() { scrollbar.setEnabled(getRows() > getVisibleRows()); scrollbar.setMaxOffset(getRows() - getVisibleRows()); } public boolean canSort() { return doSort || (!hasShiftDown() && !hasControlDown()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/SmallClientTooltipComponent.java ================================================ package com.refinedmods.refinedstorage.screen.grid; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.screens.inventory.tooltip.ClientTooltipComponent; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.network.chat.Component; import org.joml.Matrix4f; public class SmallClientTooltipComponent implements ClientTooltipComponent { private final Component component; private final float scale; public SmallClientTooltipComponent(Component component, float scale) { this.component = component; this.scale = scale; } @Override public void renderText(Font font, int x, int y, Matrix4f pose, MultiBufferSource.BufferSource buffer) { Matrix4f scaled = new Matrix4f(pose); scaled.scale(scale, scale, 1); font.drawInBatch(component, x / scale, y / scale, -1, true, scaled, buffer, Font.DisplayMode.NORMAL, 0, 15728880); } @Override public int getHeight() { return 9; } @Override public int getWidth(Font font) { return (int) (font.width(component) * scale); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/AndGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.List; import java.util.function.Predicate; public class AndGridFilter implements Predicate { private final List> andPartFilters; private AndGridFilter(List> andPartFilters) { this.andPartFilters = andPartFilters; } public static Predicate of(List> filters) { if (filters.isEmpty()) { return t -> true; } if (filters.size() == 1) { return filters.get(0); } return new AndGridFilter(filters); } @Override public boolean test(IGridStack gridStack) { for (Predicate part : andPartFilters) { if (!part.test(gridStack)) { return false; } } return true; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/CraftableGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.function.Predicate; public class CraftableGridFilter implements Predicate { private final boolean craftable; public CraftableGridFilter(boolean craftable) { this.craftable = craftable; } @Override public boolean test(IGridStack stack) { if (craftable) { return stack.isCraftable(); } else { return !stack.isCraftable() && stack.getOtherId() == null; } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/FilterGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import java.util.List; import java.util.function.Predicate; public class FilterGridFilter implements Predicate { private final List filters; public FilterGridFilter(List filters) { this.filters = filters; } @Override public boolean test(IGridStack stack) { if (filters.isEmpty()) { return true; } int lastMode = IFilter.MODE_WHITELIST; for (IFilter filter : filters) { lastMode = filter.getMode(); if (stack instanceof ItemGridStack && filter.getStack() instanceof ItemStack) { ItemStack stackInFilter = (ItemStack) filter.getStack(); if (filter.isModFilter()) { String stackModId = stack.getModId(); String filterModId = stackInFilter.getItem().getCreatorModId(stackInFilter); if (filterModId != null && filterModId.equals(stackModId)) { return filter.getMode() == IFilter.MODE_WHITELIST; } } else if (API.instance().getComparer().isEqual(((ItemGridStack) stack).getStack(), stackInFilter, filter.getCompare())) { return filter.getMode() == IFilter.MODE_WHITELIST; } } else if (stack instanceof FluidGridStack && filter.getStack() instanceof FluidStack) { FluidStack stackInFilter = (FluidStack) filter.getStack(); if (filter.isModFilter()) { ResourceLocation stackInFilterRegistryName = BuiltInRegistries.FLUID.getKey(stackInFilter.getFluid()); String stackInFilterModId = stackInFilterRegistryName.getNamespace(); if (stackInFilterModId.equalsIgnoreCase(stack.getModId())) { return filter.getMode() == IFilter.MODE_WHITELIST; } } else if (API.instance().getComparer().isEqual(((FluidGridStack) stack).getStack(), stackInFilter, filter.getCompare())) { return filter.getMode() == IFilter.MODE_WHITELIST; } } } return lastMode != IFilter.MODE_WHITELIST; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/GridFilterParser.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.api.util.IFilter; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import javax.annotation.Nullable; import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; public final class GridFilterParser { private GridFilterParser() { } public static Predicate getFilters(@Nullable IGrid grid, String query, List filters) { List> gridFilters; String[] orParts = query.split("\\|"); if (orParts.length == 1) { gridFilters = getFilters(orParts[0]); } else { List> orPartFilters = new LinkedList<>(); for (String orPart : orParts) { orPartFilters.add(AndGridFilter.of(getFilters(orPart))); } gridFilters = new LinkedList<>(); gridFilters.add(OrGridFilter.of(orPartFilters)); } if (grid != null) { if (grid.getViewType() == IGrid.VIEW_TYPE_NON_CRAFTABLES) { gridFilters.add(new CraftableGridFilter(false)); } else if (grid.getViewType() == IGrid.VIEW_TYPE_CRAFTABLES) { gridFilters.add(new CraftableGridFilter(true)); } } if (!filters.isEmpty()) { gridFilters.add(new FilterGridFilter(filters)); } return AndGridFilter.of(gridFilters); } private static List> getFilters(String query) { List> gridFilters = new LinkedList<>(); for (String part : query.toLowerCase().trim().split(" ")) { if (part.startsWith("@")) { gridFilters.add(new ModGridFilter(part.substring(1))); } else if (part.startsWith("#")) { gridFilters.add(new TooltipGridFilter(part.substring(1))); } else if (part.startsWith("$")) { gridFilters.add(new TagGridFilter(part.substring(1))); } else { gridFilters.add(new NameGridFilter(part)); } } return gridFilters; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/ModGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.function.Predicate; public class ModGridFilter implements Predicate { private final String inputModName; public ModGridFilter(String inputModName) { this.inputModName = standardify(inputModName); } @Override public boolean test(IGridStack stack) { String modId = stack.getModId(); if (modId != null) { if (modId.contains(inputModName)) { return true; } String modName = stack.getModName(); if (modName != null) { modName = standardify(modName); if (modName.contains(inputModName)) { return true; } } } return false; } private String standardify(String input) { return input.toLowerCase().replace(" ", ""); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/NameGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.function.Predicate; public class NameGridFilter implements Predicate { private final String name; public NameGridFilter(String name) { this.name = name.toLowerCase(); } @Override public boolean test(IGridStack stack) { return stack.getName().toLowerCase().contains(name); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/OrGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.List; import java.util.function.Predicate; public class OrGridFilter implements Predicate { private final List> orPartFilters; private OrGridFilter(List> orPartFilters) { this.orPartFilters = orPartFilters; } public static Predicate of(List> filters) { if (filters.isEmpty()) { return t -> false; } if (filters.size() == 1) { return filters.get(0); } return new OrGridFilter(filters); } @Override public boolean test(IGridStack gridStack) { for (Predicate part : orPartFilters) { if (part.test(gridStack)) { return true; } } return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/TagGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import java.util.function.Predicate; public class TagGridFilter implements Predicate { private final String tagName; public TagGridFilter(String tagName) { this.tagName = tagName.toLowerCase(); } @Override public boolean test(IGridStack stack) { return stack.getTags().stream().anyMatch(name -> name.toLowerCase().contains(this.tagName)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/filtering/TooltipGridFilter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.filtering; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import net.minecraft.network.chat.Component; import java.util.List; import java.util.function.Predicate; public class TooltipGridFilter implements Predicate { private final String tooltip; public TooltipGridFilter(String tooltip) { this.tooltip = tooltip.toLowerCase(); } @Override public boolean test(IGridStack stack) { List stackTooltip = stack.getTooltip(false); for (int i = 1; i < stackTooltip.size(); ++i) { if (stackTooltip.get(i).getString().toLowerCase().contains(tooltip.toLowerCase())) { return true; } } return false; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/IGridSorter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; public interface IGridSorter { boolean isApplicable(IGrid grid); int compare(IGridStack left, IGridStack right, SortingDirection direction); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/IdGridSorter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; public class IdGridSorter implements IGridSorter { @Override public boolean isApplicable(IGrid grid) { return grid.getSortingType() == IGrid.SORTING_TYPE_ID; } @Override @SuppressWarnings("deprecation") public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) { int leftId = 0; int rightId = 0; if (left.getIngredient() instanceof ItemStack && right.getIngredient() instanceof ItemStack) { leftId = Item.getId(((ItemStack) left.getIngredient()).getItem()); rightId = Item.getId(((ItemStack) right.getIngredient()).getItem()); } else if (left.getIngredient() instanceof FluidStack && right.getIngredient() instanceof FluidStack) { leftId = BuiltInRegistries.FLUID.getId(((FluidStack) left.getIngredient()).getFluid()); rightId = BuiltInRegistries.FLUID.getId(((FluidStack) right.getIngredient()).getFluid()); } if (leftId != rightId) { if (sortingDirection == SortingDirection.DESCENDING) { return Integer.compare(leftId, rightId); } else if (sortingDirection == SortingDirection.ASCENDING) { return Integer.compare(rightId, leftId); } } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/LastModifiedGridSorter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; public class LastModifiedGridSorter implements IGridSorter { @Override public boolean isApplicable(IGrid grid) { return grid.getSortingType() == IGrid.SORTING_TYPE_LAST_MODIFIED; } @Override public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) { long lt = left.getTrackerEntry() != null ? left.getTrackerEntry().getTime() : 0; long rt = right.getTrackerEntry() != null ? right.getTrackerEntry().getTime() : 0; if (lt != rt) { // For "last modified" the comparison is reversed if (sortingDirection == SortingDirection.DESCENDING) { return Long.compare(rt, lt); } else if (sortingDirection == SortingDirection.ASCENDING) { return Long.compare(lt, rt); } } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/NameGridSorter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; public class NameGridSorter implements IGridSorter { @Override public boolean isApplicable(IGrid grid) { return grid.getSortingType() == IGrid.SORTING_TYPE_NAME; } @Override public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) { String leftName = left.getName(); String rightName = right.getName(); if (sortingDirection == SortingDirection.ASCENDING) { return leftName.compareTo(rightName); } else if (sortingDirection == SortingDirection.DESCENDING) { return rightName.compareTo(leftName); } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/QuantityGridSorter.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; public class QuantityGridSorter implements IGridSorter { @Override public boolean isApplicable(IGrid grid) { return grid.getSortingType() == IGrid.SORTING_TYPE_QUANTITY; } @Override public int compare(IGridStack left, IGridStack right, SortingDirection sortingDirection) { int leftSize = left.getQuantity(); int rightSize = right.getQuantity(); if (leftSize != rightSize) { if (sortingDirection == SortingDirection.ASCENDING) { return (leftSize > rightSize) ? 1 : -1; } else if (sortingDirection == SortingDirection.DESCENDING) { return (rightSize > leftSize) ? 1 : -1; } } return 0; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/sorting/SortingDirection.java ================================================ package com.refinedmods.refinedstorage.screen.grid.sorting; public enum SortingDirection { ASCENDING, DESCENDING } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/FluidGridStack.java ================================================ package com.refinedmods.refinedstorage.screen.grid.stack; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.FluidRenderer; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.BaseScreen; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import javax.annotation.Nullable; import com.google.common.collect.Lists; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.ItemStack; import net.neoforged.neoforge.fluids.FluidStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class FluidGridStack implements IGridStack { private static final String ERROR_PLACEHOLDER = ""; private static final Logger LOGGER = LogManager.getLogger(FluidGridStack.class); private final UUID id; private final FluidStack stack; private final boolean craftable; @Nullable private UUID otherId; @Nullable private StorageTrackerEntry entry; private boolean zeroed; private Set cachedTags; private String cachedName; private List cachedTooltip; private String cachedModId; private String cachedModName; public FluidGridStack(UUID id, @Nullable UUID otherId, FluidStack stack, boolean craftable, @Nullable StorageTrackerEntry entry) { this.id = id; this.otherId = otherId; this.stack = stack; this.craftable = craftable; this.entry = entry; } public void setZeroed(boolean zeroed) { this.zeroed = zeroed; } public FluidStack getStack() { return stack; } @Override public boolean isCraftable() { return craftable; } @Override public UUID getId() { return id; } @Nullable @Override public UUID getOtherId() { return otherId; } @Override public void updateOtherId(@Nullable UUID otherId) { this.otherId = otherId; } @Override public String getName() { if (cachedName == null) { try { cachedName = stack.getDisplayName().getString(); } catch (Throwable t) { LOGGER.warn("Could not retrieve fluid name of {}", BuiltInRegistries.FLUID.getKey(stack.getFluid())); cachedName = ERROR_PLACEHOLDER; } } return cachedName; } @Override public String getModId() { if (cachedModId == null) { ResourceLocation registryName = BuiltInRegistries.FLUID.getKey(stack.getFluid()); if (registryName != null) { cachedModId = registryName.getNamespace(); } else { cachedModId = ERROR_PLACEHOLDER; } } return cachedModId; } @Override public String getModName() { if (cachedModName == null) { cachedModName = ItemGridStack.getModNameByModId(getModId()); if (cachedModName == null) { cachedModName = ERROR_PLACEHOLDER; } } return cachedModName; } @Override public Set getTags() { if (cachedTags == null) { cachedTags = BuiltInRegistries.FLUID.getResourceKey(stack.getFluid()) .flatMap(k -> BuiltInRegistries.FLUID.getHolder(k) .map(holder -> holder.tags() .map(TagKey::location) .map(ResourceLocation::getPath) .collect(Collectors.toSet()))) .orElse(Collections.emptySet()); } return cachedTags; } @Override public List getTooltip(boolean bypassCache) { if (bypassCache || cachedTooltip == null) { List tooltip; try { tooltip = Lists.newArrayList(stack.getDisplayName()); } catch (Throwable t) { LOGGER.warn("Could not retrieve fluid tooltip of {}", BuiltInRegistries.FLUID.getKey(stack.getFluid())); tooltip = Lists.newArrayList(Component.literal(ERROR_PLACEHOLDER)); } if (bypassCache) { return tooltip; } else { cachedTooltip = tooltip; } } return cachedTooltip; } @Override public int getQuantity() { // The isCraftable check is needed so sorting is applied correctly return isCraftable() || zeroed ? 0 : stack.getAmount(); } @Override public void setQuantity(int amount) { if (amount <= 0) { setZeroed(true); } else { stack.setAmount(amount); } } @Override public String getFormattedFullQuantity() { if (zeroed) { return "0 mB"; } return API.instance().getQuantityFormatter().format(getQuantity()) + " mB"; } @Override public void draw(GuiGraphics graphics, BaseScreen screen, int x, int y) { FluidRenderer.INSTANCE.render(graphics, x, y, stack); String text; int color = RenderSettings.INSTANCE.getSecondaryColor(); if (zeroed) { text = "0"; color = 16733525; } else if (isCraftable()) { text = I18n.get("gui.refinedstorage.grid.craft"); } else { text = API.instance().getQuantityFormatter().formatInBucketFormWithOnlyTrailingDigitsIfZero(getQuantity()); } screen.renderQuantity(graphics, x, y, text, color); } @Override public Object getIngredient() { return getStack(); } @Nullable @Override public StorageTrackerEntry getTrackerEntry() { return entry; } @Override public void setTrackerEntry(@Nullable StorageTrackerEntry entry) { this.entry = entry; } public static FluidGridStack of( final IStorageCache cache, @Nullable final IStackList craftablesList, final IStorageTracker storageTracker, final StackListResult delta ) { StackListEntry craftingEntry = craftablesList == null ? null : cache.getCraftablesList().getEntry(delta.getStack(), IComparer.COMPARE_NBT); return new FluidGridStack( delta.getId(), craftingEntry != null ? craftingEntry.getId() : null, delta.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player false, storageTracker.get(delta.getStack()) ); } public static FluidGridStack of( final StackListEntry entry, final IStorageTracker storageTracker, @Nullable final IStackList oppositeList, final boolean craftable ) { StackListEntry otherEntry = oppositeList == null ? null : oppositeList.getEntry(entry.getStack(), IComparer.COMPARE_NBT); return new FluidGridStack( entry.getId(), otherEntry != null ? otherEntry.getId() : null, entry.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player craftable, storageTracker.get(entry.getStack()) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/IGridStack.java ================================================ package com.refinedmods.refinedstorage.screen.grid.stack; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; import javax.annotation.Nullable; import java.util.List; import java.util.Set; import java.util.UUID; public interface IGridStack { UUID getId(); @Nullable UUID getOtherId(); void updateOtherId(@Nullable UUID otherId); String getName(); String getModId(); String getModName(); Set getTags(); List getTooltip(boolean bypassCache); int getQuantity(); void setQuantity(int amount); String getFormattedFullQuantity(); void draw(GuiGraphics graphics, BaseScreen screen, int x, int y); Object getIngredient(); @Nullable StorageTrackerEntry getTrackerEntry(); void setTrackerEntry(@Nullable StorageTrackerEntry entry); boolean isCraftable(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/stack/ItemGridStack.java ================================================ package com.refinedmods.refinedstorage.screen.grid.stack; import com.refinedmods.refinedstorage.api.storage.cache.IStorageCache; import com.refinedmods.refinedstorage.api.storage.tracker.IStorageTracker; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.api.util.IStackList; import com.refinedmods.refinedstorage.api.util.StackListEntry; import com.refinedmods.refinedstorage.api.util.StackListResult; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.RenderUtils; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; import javax.annotation.Nullable; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.ItemStack; import net.neoforged.fml.ModContainer; import net.neoforged.fml.ModList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; public class ItemGridStack implements IGridStack { private static final String ERROR_PLACEHOLDER = ""; private static final Logger LOGGER = LogManager.getLogger(ItemGridStack.class); private final ItemStack stack; private UUID id; @Nullable private UUID otherId; private boolean craftable; @Nullable private StorageTrackerEntry entry; private boolean zeroed; private Set cachedTags; private String cachedName; private String cachedModId; private String cachedModName; private List cachedTooltip; public ItemGridStack(ItemStack stack) { this.stack = stack; } public ItemGridStack(UUID id, @Nullable UUID otherId, ItemStack stack, boolean craftable, StorageTrackerEntry entry) { this.id = id; this.otherId = otherId; this.stack = stack; this.craftable = craftable; this.entry = entry; } @Nullable static String getModNameByModId(String modId) { Optional modContainer = ModList.get().getModContainerById(modId); return modContainer.map(container -> container.getModInfo().getDisplayName()).orElse(null); } public void setZeroed(boolean zeroed) { this.zeroed = zeroed; } public ItemStack getStack() { return stack; } @Override public boolean isCraftable() { return craftable; } @Override public UUID getId() { return id; } @Nullable @Override public UUID getOtherId() { return otherId; } @Override public void updateOtherId(@Nullable UUID otherId) { this.otherId = otherId; } @Override public String getName() { if (cachedName == null) { try { cachedName = stack.getHoverName().getString(); } catch (Throwable t) { LOGGER.warn("Could not retrieve item name of {}", BuiltInRegistries.ITEM.getKey(stack.getItem())); cachedName = ERROR_PLACEHOLDER; } } return cachedName; } @Override public String getModId() { if (cachedModId == null) { cachedModId = stack.getItem().getCreatorModId(stack); if (cachedModId == null) { cachedModId = ERROR_PLACEHOLDER; } cachedModId = cachedModId.toLowerCase().replace(" ", ""); } return cachedModId; } @Override public String getModName() { if (cachedModName == null) { cachedModName = getModNameByModId(getModId()); if (cachedModName == null) { cachedModName = ERROR_PLACEHOLDER; } } return cachedModName; } @Override public Set getTags() { if (cachedTags == null) { cachedTags = BuiltInRegistries.ITEM.getResourceKey(stack.getItem()) .flatMap(k -> BuiltInRegistries.ITEM.getHolder(k) .map(holder -> holder.tags() .map(TagKey::location) .map(ResourceLocation::getPath) .collect(Collectors.toSet()))) .orElse(Collections.emptySet()); } return cachedTags; } @Override public List getTooltip(boolean bypassCache) { if (bypassCache || cachedTooltip == null) { List tooltip; try { tooltip = RenderUtils.getTooltipFromItem(stack); } catch (Throwable t) { LOGGER.warn("Could not retrieve item tooltip of {}", BuiltInRegistries.ITEM.getKey(stack.getItem())); tooltip = new ArrayList<>(); tooltip.add(Component.literal(ERROR_PLACEHOLDER)); } if (bypassCache) { return tooltip; } else { cachedTooltip = tooltip; } } return cachedTooltip; } @Override public int getQuantity() { // The isCraftable check is needed so sorting is applied correctly return isCraftable() || zeroed ? 0 : stack.getCount(); } @Override public void setQuantity(int amount) { if (amount <= 0) { setZeroed(true); } else { stack.setCount(amount); } } @Override public String getFormattedFullQuantity() { if (zeroed) { return "0"; } return API.instance().getQuantityFormatter().format(getQuantity()); } @Override public void draw(GuiGraphics graphics, BaseScreen screen, int x, int y) { String text = null; int color = RenderSettings.INSTANCE.getSecondaryColor(); if (zeroed) { text = "0"; color = 16733525; } else if (craftable) { text = I18n.get("gui.refinedstorage.grid.craft"); } else if (stack.getCount() > 1) { text = API.instance().getQuantityFormatter().formatWithUnits(getQuantity()); } screen.renderItem(graphics, x, y, stack, true, text, color); } @Override public Object getIngredient() { return getStack(); } @Nullable @Override public StorageTrackerEntry getTrackerEntry() { return entry; } @Override public void setTrackerEntry(@Nullable StorageTrackerEntry entry) { this.entry = entry; } public static ItemGridStack of( final IStorageCache cache, @Nullable final IStackList craftablesList, final IStorageTracker storageTracker, final StackListResult delta ) { StackListEntry craftingEntry = craftablesList == null ? null : cache.getCraftablesList().getEntry(delta.getStack(), IComparer.COMPARE_NBT); return new ItemGridStack( delta.getId(), craftingEntry != null ? craftingEntry.getId() : null, delta.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player false, storageTracker.get(delta.getStack()) ); } public static ItemGridStack of( final StackListEntry entry, final IStorageTracker storageTracker, @Nullable final IStackList oppositeList, final boolean craftable ) { StackListEntry otherEntry = oppositeList == null ? null : oppositeList.getEntry(entry.getStack(), IComparer.COMPARE_NBT); return new ItemGridStack( entry.getId(), otherEntry != null ? otherEntry.getId() : null, entry.getStack().copy(), // copy is very important as the same stack will be shared between server<->client on single player craftable, storageTracker.get(entry.getStack()) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/view/GridViewImpl.java ================================================ package com.refinedmods.refinedstorage.screen.grid.view; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.integration.jei.IngredientTracker; import com.refinedmods.refinedstorage.screen.grid.GridScreen; import com.refinedmods.refinedstorage.screen.grid.filtering.GridFilterParser; import com.refinedmods.refinedstorage.screen.grid.sorting.IGridSorter; import com.refinedmods.refinedstorage.screen.grid.sorting.SortingDirection; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import javax.annotation.Nullable; import java.util.*; import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; public class GridViewImpl implements IGridView { protected final Map map = new HashMap<>(); private final GridScreen screen; private final IGridSorter defaultSorter; private final List sorters; private boolean canCraft; private boolean active = false; private List stacks = new ArrayList<>(); private List> deltaListeners = new ArrayList<>(); public GridViewImpl(GridScreen screen, IGridSorter defaultSorter, List sorters) { this.screen = screen; this.defaultSorter = defaultSorter; this.sorters = sorters; } @Override public List getStacks() { return stacks; } @Override public void setStacks(List stacks) { map.clear(); for (IGridStack stack : stacks) { map.put(stack.getId(), stack); } } @Override public Collection getAllStacks() { return map.values(); } @Nullable @Override public IGridStack get(UUID id) { return map.get(id); } @Override public void sort() { if (!screen.canSort()) { return; } forceSort(); } @Override public void forceSort() { if (screen.getGrid().isGridActive()) { this.stacks = map.values().stream() .filter(getActiveFilters()) .sorted(getActiveSort()) .collect(Collectors.toCollection(ArrayList::new)); this.active = true; } else { this.stacks = new ArrayList<>(); this.active = false; } this.screen.updateScrollbar(); } @Override public void addDeltaListener(Consumer listener) { deltaListeners.add(listener); } @Override public void removed() { deltaListeners.clear(); IngredientTracker.invalidate(); } private Comparator getActiveSort() { IGrid grid = screen.getGrid(); SortingDirection sortingDirection = grid.getSortingDirection() == IGrid.SORTING_DIRECTION_DESCENDING ? SortingDirection.DESCENDING : SortingDirection.ASCENDING; return Stream.concat(Stream.of(defaultSorter), sorters.stream().filter(s -> s.isApplicable(grid))) .map(sorter -> (Comparator) (o1, o2) -> sorter.compare(o1, o2, sortingDirection)) .reduce((l, r) -> r.thenComparing(l)) .orElseThrow(IllegalStateException::new); // There is at least 1 value in the stream (i.e. defaultSorter) } private Predicate getActiveFilters() { IGrid grid = screen.getGrid(); Predicate filters = GridFilterParser.getFilters( grid, screen.getSearchFieldText(), (grid.getTabSelected() >= 0 && grid.getTabSelected() < grid.getTabs().size()) ? grid.getTabs().get(grid.getTabSelected()).getFilters() : grid.getFilters() ); if (screen.getGrid().getViewType() != IGrid.VIEW_TYPE_CRAFTABLES) { return stack -> { // If this is a crafting stack, // and there is a regular matching stack in the view too, // and we aren't in "view only craftables" mode, // we don't want the duplicate stacks and we will remove this stack. if (stack.isCraftable() && stack.getOtherId() != null && map.containsKey(stack.getOtherId())) { return false; } return filters.test(stack); }; } else { return filters; } } @Override public void postChange(IGridStack stack, int delta) { if (!this.active) { return; } // COMMENT 1 (about this if check in general) // Update the other id reference if needed. // Taking a stack out - and then re-inserting it - gives the new stack a new ID // With that new id, the reference for the crafting stack would be outdated. // COMMENT 2 (about map.containsKey(stack.getOtherId())) // This check is needed or the .updateOtherId() call will crash with a NPE in high-update environments. // 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. // (This is because of the executeLater system) // This causes the .updateOtherId() to fail with a NPE because the map is still empty or the IDs mismatch. // 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. // This means that on the second delta packet it would still crash because the map wouldn't be empty anymore. IGridStack craftingStack; if (!stack.isCraftable() && stack.getOtherId() != null && map.containsKey(stack.getOtherId())) { craftingStack = map.get(stack.getOtherId()); craftingStack.updateOtherId(stack.getId()); craftingStack.setTrackerEntry(stack.getTrackerEntry()); } else { craftingStack = null; } Predicate activeFilters = getActiveFilters(); IGridStack existing = map.get(stack.getId()); boolean stillExists = true; boolean shouldSort = screen.canSort(); if (existing == null) { stack.setQuantity(delta); map.put(stack.getId(), stack); existing = stack; if (craftingStack != null && shouldSort && activeFilters.test(existing)) { stacks.remove(craftingStack); } deltaListeners.forEach(consumer -> consumer.accept(stack)); } else { if (shouldSort) { stacks.remove(existing); } existing.setQuantity(existing.getQuantity() + delta); if (existing.getQuantity() <= 0) { map.remove(existing.getId()); stillExists = false; if (craftingStack != null && shouldSort && activeFilters.test(existing) && activeFilters.test(craftingStack)) { addStack(craftingStack); } } existing.setTrackerEntry(stack.getTrackerEntry()); } if (shouldSort) { if (stillExists && activeFilters.test(existing)) { addStack(existing); } this.screen.updateScrollbar(); } } private void addStack(IGridStack stack) { int insertionPos = Collections.binarySearch(stacks, stack, getActiveSort()); if (insertionPos < 0) { insertionPos = -insertionPos - 1; } stacks.add(insertionPos, stack); } @Override public void setCanCraft(boolean canCraft) { this.canCraft = canCraft; } @Override public boolean canCraft() { return canCraft; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/grid/view/IGridView.java ================================================ package com.refinedmods.refinedstorage.screen.grid.view; import com.refinedmods.refinedstorage.screen.grid.stack.IGridStack; import javax.annotation.Nullable; import java.util.Collection; import java.util.List; import java.util.UUID; import java.util.function.Consumer; public interface IGridView { List getStacks(); void setStacks(List stacks); @Nullable IGridStack get(UUID id); Collection getAllStacks(); void postChange(IGridStack stack, int delta); void setCanCraft(boolean canCraft); boolean canCraft(); void sort(); void forceSort(); void addDeltaListener(Consumer listener); void removed(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/ScrollbarWidget.java ================================================ package com.refinedmods.refinedstorage.screen.widget; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.integration.jei.GridRecipeTransferHandler; import com.refinedmods.refinedstorage.integration.jei.JeiIntegration; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.events.GuiEventListener; import java.util.LinkedList; import java.util.List; public class ScrollbarWidget implements GuiEventListener { private static final float SCROLLER_HEIGHT = 15; private final int x; private final int y; private final int width; private final int height; private final List listeners = new LinkedList<>(); private final BaseScreen screen; private boolean enabled = false; private int offset; private int maxOffset; private boolean clicked = false; private boolean small = false; private boolean focused = false; public ScrollbarWidget(BaseScreen screen, int x, int y, int width, int height) { this.screen = screen; this.x = x; this.y = y; this.width = width; this.height = height; } public ScrollbarWidget(BaseScreen screen, int x, int y, int width, int height, boolean small) { this(screen, x, y, width, height); this.small = small; } public void addListener(ScrollbarWidgetListener listener) { listeners.add(listener); } public int getWidth() { return width; } public int getHeight() { return height; } public boolean isEnabled() { return enabled; } public void setEnabled(boolean enabled) { this.enabled = enabled; } public void render(GuiGraphics graphics) { RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); if (small) { 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); } else { 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); } } @Override public boolean mouseClicked(double mx, double my, int button) { mx -= screen.getGuiLeft(); my -= screen.getGuiTop(); if (button == 0 && RenderUtils.inBounds(x, y, width, height, mx, my)) { // Prevent accidental scrollbar click after clicking recipe transfer button if (JeiIntegration.isLoaded() && GridRecipeTransferHandler.INSTANCE.hasTransferredRecently()) { return false; } updateOffset(my); clicked = true; return true; } return false; } @Override public void mouseMoved(double mx, double my) { mx -= screen.getGuiLeft(); my -= screen.getGuiTop(); if (clicked && RenderUtils.inBounds(x, y, width, height, mx, my)) { updateOffset(my); } } private void updateOffset(double my) { setOffset((int) Math.floor((float) (my - y) / (float) (height - SCROLLER_HEIGHT) * (float) maxOffset)); } @Override public boolean mouseReleased(double mx, double my, int button) { if (clicked) { clicked = false; return true; } return false; } @Override public boolean mouseScrolled(double x, double y, double z, double delta) { if (isEnabled()) { setOffset(offset + Math.max(Math.min(-(int) delta, 1), -1)); return true; } return false; } @Override public void setFocused(boolean focused) { this.focused = focused; } @Override public boolean isFocused() { return focused; } public void setMaxOffset(int maxOffset) { this.maxOffset = maxOffset; if (offset > maxOffset) { this.offset = Math.max(0, maxOffset); } } public int getOffset() { return offset; } public void setOffset(int offset) { int oldOffset = this.offset; if (offset >= 0 && offset <= maxOffset) { this.offset = offset; listeners.forEach(l -> l.onOffsetChanged(oldOffset, offset)); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/ScrollbarWidgetListener.java ================================================ package com.refinedmods.refinedstorage.screen.widget; public interface ScrollbarWidgetListener { void onOffsetChanged(int oldOffset, int newOffset); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/SearchWidget.java ================================================ package com.refinedmods.refinedstorage.screen.widget; import com.refinedmods.refinedstorage.RSKeyBindings; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.integration.jei.JeiIntegration; import com.refinedmods.refinedstorage.integration.jei.RSJeiPlugin; import com.refinedmods.refinedstorage.render.RenderSettings; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.network.chat.Component; import org.lwjgl.glfw.GLFW; import java.util.ArrayList; import java.util.List; public class SearchWidget extends EditBox { private static final List HISTORY = new ArrayList<>(); private int mode; private int historyIndex = -1; public SearchWidget(Font fontRenderer, int x, int y, int width) { super(fontRenderer, x, y, width, fontRenderer.lineHeight, Component.literal("")); this.setBordered(false); this.setVisible(true); this.setTextColor(RenderSettings.INSTANCE.getSecondaryColor()); } public void updateJei() { if (canSyncToJEINow()) { RSJeiPlugin.getRuntime().getIngredientFilter().setFilterText(getValue()); } } private boolean canSyncToJEINow() { return IGrid.doesSearchBoxModeUseJEI(this.mode) && JeiIntegration.isLoaded(); } private boolean canSyncFromJEINow() { return (this.mode == IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY || this.mode == IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED) && JeiIntegration.isLoaded(); } @Override public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { boolean result = super.mouseClicked(mouseX, mouseY, mouseButton); boolean clickedWidget = mouseX >= this.getX() && mouseX < this.getX() + this.width && mouseY >= this.getY() && mouseY < this.getY() + this.height; if (clickedWidget && mouseButton == 1) { // On right click, clear the widget and focus, save history if necessary. if (isFocused()) { saveHistory(); } setValue(""); setFocused(true); } if (!clickedWidget && isFocused()) { // If we are focused, and we click outside the search box, lose focus. saveHistory(); setFocused(false); } return result; } @Override public boolean keyPressed(int keyCode, int scanCode, int modifier) { if (super.keyPressed(keyCode, scanCode, modifier)) { return true; } if (isFocused()) { if (keyCode == GLFW.GLFW_KEY_UP) { updateHistory(-1); } else if (keyCode == GLFW.GLFW_KEY_DOWN) { updateHistory(1); } else if (keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER) { saveHistory(); if (canLoseFocus) { setFocused(false); } } else if (keyCode == GLFW.GLFW_KEY_ESCAPE) { saveHistory(); if (!canLoseFocus) { // If we can't lose focus, // and we press escape, // we unfocus ourselves, // and close the screen immediately. setFocused(false); return false; // Bubble the event up to the screen. } else { // If we can lose focus, // and we press escape, // we unfocus ourselves. // On the next escape press, the screen will close. setFocused(false); return true; // Swallow } } } if (BaseScreen.isKeyDown(RSKeyBindings.FOCUS_SEARCH_BAR) && canLoseFocus) { setFocused(!isFocused()); saveHistory(); return true; } return isFocused() && canConsumeInput() && keyCode != GLFW.GLFW_KEY_ESCAPE; } private void updateHistory(int delta) { if (HISTORY.isEmpty()) { return; } if (historyIndex == -1) { historyIndex = HISTORY.size(); } historyIndex += delta; if (historyIndex < 0) { historyIndex = 0; } else if (historyIndex > HISTORY.size() - 1) { historyIndex = HISTORY.size() - 1; if (delta == 1) { setValue(""); return; } } setValue(HISTORY.get(historyIndex)); } private void saveHistory() { if (!HISTORY.isEmpty() && HISTORY.get(HISTORY.size() - 1).equals(getValue())) { return; } if (!getValue().trim().isEmpty()) { HISTORY.add(getValue()); } } public void setMode(int mode) { this.mode = mode; this.setCanLoseFocus(!IGrid.isSearchBoxModeWithAutoselection(mode)); this.setFocused(IGrid.isSearchBoxModeWithAutoselection(mode)); if (canSyncFromJEINow()) { setTextFromJEI(); } } private void setTextFromJEI() { final String filterText = RSJeiPlugin.getRuntime().getIngredientFilter().getFilterText(); if (!getValue().equals(filterText)) { setValue(filterText); } } @Override public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { if (canSyncFromJEINow() && RSJeiPlugin.getRuntime().getIngredientListOverlay().hasKeyboardFocus()) { setTextFromJEI(); } super.renderWidget(graphics, mouseX, mouseY, partialTicks); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/SmallCheckboxWidget.java ================================================ package com.refinedmods.refinedstorage.screen.widget; import java.util.function.Consumer; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; public class SmallCheckboxWidget extends AbstractButton { private static final ResourceLocation CHECKBOX_SELECTED_HIGHLIGHTED_SPRITE = new ResourceLocation("widget/checkbox_selected_highlighted"); private static final ResourceLocation CHECKBOX_SELECTED_SPRITE = new ResourceLocation("widget/checkbox_selected"); private static final ResourceLocation CHECKBOX_HIGHLIGHTED_SPRITE = new ResourceLocation("widget/checkbox_highlighted"); private static final ResourceLocation CHECKBOX_SPRITE = new ResourceLocation("widget/checkbox"); private static final int BOX_WIDTH = 13; private final Consumer onPress; private boolean shadow = true; private boolean selected; public SmallCheckboxWidget(int x, int y, Component text, boolean isSelected, Consumer onPress) { super( x, y, Minecraft.getInstance().font.width(text.getString()) + BOX_WIDTH + 4, 10, text ); this.selected = isSelected; this.onPress = onPress; } public void setSelected(boolean value) { this.selected = value; } public boolean isSelected() { return selected; } public void setShadow(boolean shadow) { this.shadow = shadow; } @Override public void onPress() { this.selected = !selected; this.onPress.accept(this); } @Override public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { ResourceLocation texture; if (this.selected) { texture = isFocused() ? CHECKBOX_SELECTED_HIGHLIGHTED_SPRITE : CHECKBOX_SELECTED_SPRITE; } else { texture = isFocused() ? CHECKBOX_HIGHLIGHTED_SPRITE : CHECKBOX_SPRITE; } int color = 14737632; if (!active) { color = 10526880; } else if (packedFGColor != 0) { color = packedFGColor; } int i = BOX_WIDTH; int j = this.getX() + i + 4; int k = this.getY() + (this.height - 8) / 2; graphics.blitSprite(texture, this.getX(), this.getY(), i, i); graphics.setColor(1.0F, 1.0F, 1.0F, 1.0F); graphics.drawString(Minecraft.getInstance().font, this.getMessage(), j, k, color, shadow); } @Override protected void updateWidgetNarration(NarrationElementOutput output) { output.add(NarratedElementType.TITLE, this.createNarrationMessage()); if (this.active) { if (this.isFocused()) { output.add(NarratedElementType.USAGE, Component.translatable("narration.checkbox.usage.focused")); } else { output.add(NarratedElementType.USAGE, Component.translatable("narration.checkbox.usage.hovered")); } } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/TabListWidget.java ================================================ package com.refinedmods.refinedstorage.screen.widget; import com.refinedmods.refinedstorage.api.network.grid.IGridTab; import com.refinedmods.refinedstorage.apiimpl.render.ElementDrawers; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import net.minecraft.world.inventory.AbstractContainerMenu; import java.util.LinkedList; import java.util.List; import java.util.function.Supplier; public class TabListWidget { private final BaseScreen screen; private final ElementDrawers drawers; private final Supplier> tabs; private final int tabsPerPage; private final Supplier pages; private final Supplier page; private final Supplier selected; private final List listeners = new LinkedList<>(); private int tabHovering; private boolean hadTabs; private Button left; private Button right; public TabListWidget(BaseScreen screen, ElementDrawers drawers, Supplier> tabs, Supplier pages, Supplier page, Supplier selected, int tabsPerPage) { this.screen = screen; this.drawers = drawers; this.tabs = tabs; this.pages = pages; this.page = page; this.selected = selected; this.tabsPerPage = tabsPerPage; } public void init(int width) { 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))); 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))); } public void addListener(ITabListListener listener) { listeners.add(listener); } public void drawForeground(GuiGraphics graphics, int x, int y, int mouseX, int mouseY, boolean visible) { this.tabHovering = -1; if (visible) { int j = 0; for (int i = page.get() * tabsPerPage; i < (page.get() * tabsPerPage) + tabsPerPage; ++i) { if (i < tabs.get().size()) { drawTab(graphics, tabs.get().get(i), true, x, y, i, j); if (RenderUtils.inBounds(x + getXOffset() + ((IGridTab.TAB_WIDTH + 1) * j), y, IGridTab.TAB_WIDTH, IGridTab.TAB_HEIGHT - (i == selected.get() ? 2 : 7), mouseX, mouseY)) { this.tabHovering = i; } j++; } } } } public void update() { boolean hasTabs = !tabs.get().isEmpty(); if (this.hadTabs != hasTabs) { this.hadTabs = hasTabs; screen.init(); } if (page.get() > pages.get()) { listeners.forEach(t -> t.onPageChanged(pages.get())); } left.visible = pages.get() > 0; right.visible = pages.get() > 0; left.active = page.get() > 0; right.active = page.get() < pages.get(); } public void drawBackground(GuiGraphics graphics, int x, int y) { int j = 0; for (int i = page.get() * tabsPerPage; i < (page.get() * tabsPerPage) + tabsPerPage; ++i) { if (i < tabs.get().size()) { drawTab(graphics, tabs.get().get(i), false, x, y, i, j++); } } } public int getHeight() { return !tabs.get().isEmpty() ? IGridTab.TAB_HEIGHT - 4 : 0; } private int getXOffset() { if (pages.get() > 0) { return 24; } return 0; } private void drawTab(GuiGraphics graphics, IGridTab tab, boolean foregroundLayer, int x, int y, int index, int num) { boolean isSelected = index == selected.get(); if ((foregroundLayer && !isSelected) || (!foregroundLayer && isSelected)) { return; } int tx = x + getXOffset() + ((IGridTab.TAB_WIDTH + 1) * num); int ty = y; if (!isSelected) { ty += 3; } int uvx; int uvy = 225; int tbw = IGridTab.TAB_WIDTH; int otx = tx; if (isSelected) { uvx = 227; if (num > 0 || getXOffset() != 0) { uvx = 226; uvy = 194; tbw++; tx--; } } else { uvx = 199; } graphics.blit(BaseScreen.ICONS_TEXTURE, tx, ty, uvx, uvy, tbw, IGridTab.TAB_HEIGHT); tab.drawIcon(graphics, otx + 6, ty + 9 - (!isSelected ? 3 : 0), drawers.getItemDrawer(), drawers.getFluidDrawer()); } public void drawTooltip(GuiGraphics graphics, Font font, int mouseX, int mouseY) { if (tabHovering >= 0 && tabHovering < tabs.get().size()) { tabs.get().get(tabHovering).drawTooltip(font, graphics, mouseX, mouseY); } } public boolean mouseClicked() { if (tabHovering >= 0 && tabHovering < tabs.get().size()) { listeners.forEach(t -> t.onSelectionChanged(tabHovering)); return true; } return false; } public interface ITabListListener { void onSelectionChanged(int tab); void onPageChanged(int page); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/AccessTypeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.storage.AccessType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.AccessTypeUtils; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class AccessTypeSideButton extends SideButton { private final BlockEntitySynchronizationParameter parameter; public AccessTypeSideButton(BaseScreen screen, BlockEntitySynchronizationParameter parameter) { super(screen); this.parameter = parameter; } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * parameter.getValue().getId(), 240, 16, 16); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.access_type") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.access_type." + parameter.getValue().getId()); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(parameter, AccessTypeUtils.getAccessType(parameter.getValue().getId() + 1)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/ConstructorDropSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.blockentity.ConstructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.container.ConstructorContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class ConstructorDropSideButton extends SideButton { public ConstructorDropSideButton(BaseScreen screen) { super(screen); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + (Boolean.TRUE.equals(ConstructorBlockEntity.DROP.getValue()) ? 16 : 0), 16, 16, 16); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.constructor.drop") + "\n" + ChatFormatting.GRAY + I18n.get(Boolean.TRUE.equals(ConstructorBlockEntity.DROP.getValue()) ? "gui.yes" : "gui.no"); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(ConstructorBlockEntity.DROP, !ConstructorBlockEntity.DROP.getValue()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/CrafterManagerSearchBoxModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.screen.CrafterManagerScreen; import com.refinedmods.refinedstorage.blockentity.CrafterManagerBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; public class CrafterManagerSearchBoxModeSideButton extends SearchBoxModeSideButton { public CrafterManagerSearchBoxModeSideButton(CrafterManagerScreen screen) { super(screen); } @Override protected int getSearchBoxMode() { return ((CrafterManagerScreen) screen).getCrafterManager().getSearchBoxMode(); } @Override protected void setSearchBoxMode(int mode) { BlockEntitySynchronizationManager.setParameter(CrafterManagerBlockEntity.SEARCH_BOX_MODE, mode); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/CrafterModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.container.CrafterContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class CrafterModeSideButton extends SideButton { public CrafterModeSideButton(BaseScreen screen) { super(screen); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.crafter_mode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.crafter_mode." + CrafterBlockEntity.MODE.getValue()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, CrafterBlockEntity.MODE.getValue() * 16, 0, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(CrafterBlockEntity.MODE, CrafterBlockEntity.MODE.getValue() + 1); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/DestructorPickupSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.container.DestructorContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.blockentity.DestructorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class DestructorPickupSideButton extends SideButton { public DestructorPickupSideButton(BaseScreen screen) { super(screen); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + (Boolean.TRUE.equals(DestructorBlockEntity.PICKUP.getValue()) ? 0 : 16), 0, 16, 16); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.destructor.pickup") + "\n" + ChatFormatting.GRAY + I18n.get(Boolean.TRUE.equals(DestructorBlockEntity.PICKUP.getValue()) ? "gui.yes" : "gui.no"); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(DestructorBlockEntity.PICKUP, !DestructorBlockEntity.PICKUP.getValue()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/DetectorModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode; import com.refinedmods.refinedstorage.blockentity.DetectorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.container.DetectorContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class DetectorModeSideButton extends SideButton { public DetectorModeSideButton(BaseScreen screen) { super(screen); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.detector.mode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.detector.mode." + DetectorBlockEntity.MODE.getValue()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, DetectorBlockEntity.MODE.getValue() * 16, 176, 16, 16); } @Override public void onPress() { int mode = DetectorBlockEntity.MODE.getValue(); if (mode == DetectorNetworkNode.MODE_EQUAL) { mode = DetectorNetworkNode.MODE_ABOVE; } else if (mode == DetectorNetworkNode.MODE_ABOVE) { mode = DetectorNetworkNode.MODE_UNDER; } else if (mode == DetectorNetworkNode.MODE_UNDER) { mode = DetectorNetworkNode.MODE_EQUAL; } BlockEntitySynchronizationManager.setParameter(DetectorBlockEntity.MODE, mode); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/ExactModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class ExactModeSideButton extends SideButton { private static final int MASK = IComparer.COMPARE_NBT; private final BlockEntitySynchronizationParameter parameter; public ExactModeSideButton(BaseScreen screen, BlockEntitySynchronizationParameter parameter) { super(screen); this.parameter = parameter; } @Override protected String getSideButtonTooltip() { String tooltip = I18n.get("sidebutton.refinedstorage.exact_mode") + "\n" + ChatFormatting.GRAY; if ((parameter.getValue() & MASK) == MASK) { tooltip += I18n.get("sidebutton.refinedstorage.exact_mode.on"); } else { tooltip += I18n.get("sidebutton.refinedstorage.exact_mode.off"); } return tooltip; } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { int ty = 16 * 12; int tx = (parameter.getValue() & MASK) == MASK ? 0 : 16; graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, tx, ty, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() ^ MASK); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/FilterTypeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.screen.FilterScreen; import com.refinedmods.refinedstorage.blockentity.config.IType; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class FilterTypeSideButton extends SideButton { private final FilterScreen filterScreen; public FilterTypeSideButton(FilterScreen filterScreen) { super(filterScreen); this.filterScreen = filterScreen; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.type") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.type." + filterScreen.getType()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * filterScreen.getType(), 128, 16, 16); } @Override public void onPress() { filterScreen.setType(filterScreen.getType() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS); filterScreen.sendUpdate(); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSearchBoxModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.screen.grid.GridScreen; public class GridSearchBoxModeSideButton extends SearchBoxModeSideButton { public GridSearchBoxModeSideButton(GridScreen screen) { super(screen); } @Override protected int getSearchBoxMode() { return ((GridScreen) screen).getGrid().getSearchBoxMode(); } @Override protected void setSearchBoxMode(int mode) { ((GridScreen) screen).getGrid().onSearchBoxModeChanged(mode); ((GridScreen) screen).getSearchField().setMode(mode); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSizeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import java.util.function.Consumer; import java.util.function.Supplier; public class GridSizeSideButton extends SideButton { private final Supplier sizeSupplier; private final Consumer listener; public GridSizeSideButton(BaseScreen screen, Supplier sizeSupplier, Consumer listener) { super(screen); this.sizeSupplier = sizeSupplier; this.listener = listener; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.grid.size") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.grid.size." + this.sizeSupplier.get()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { int size = this.sizeSupplier.get(); int tx = 0; if (size == IGrid.SIZE_STRETCH) { tx = 48; } else if (size == IGrid.SIZE_SMALL) { tx = 0; } else if (size == IGrid.SIZE_MEDIUM) { tx = 16; } else if (size == IGrid.SIZE_LARGE) { tx = 32; } graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 64 + tx, 64, 16, 16); } @Override public void onPress() { int size = this.sizeSupplier.get(); if (size == IGrid.SIZE_STRETCH) { size = IGrid.SIZE_SMALL; } else if (size == IGrid.SIZE_SMALL) { size = IGrid.SIZE_MEDIUM; } else if (size == IGrid.SIZE_MEDIUM) { size = IGrid.SIZE_LARGE; } else if (size == IGrid.SIZE_LARGE) { size = IGrid.SIZE_STRETCH; } this.listener.accept(size); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSortingDirectionSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class GridSortingDirectionSideButton extends SideButton { private final IGrid grid; public GridSortingDirectionSideButton(BaseScreen screen, IGrid grid) { super(screen); this.grid = grid; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.grid.sorting.direction") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.grid.sorting.direction." + grid.getSortingDirection()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, grid.getSortingDirection() * 16, 16, 16, 16); } @Override public void onPress() { int dir = grid.getSortingDirection(); if (dir == IGrid.SORTING_DIRECTION_ASCENDING) { dir = IGrid.SORTING_DIRECTION_DESCENDING; } else if (dir == IGrid.SORTING_DIRECTION_DESCENDING) { dir = IGrid.SORTING_DIRECTION_ASCENDING; } grid.onSortingDirectionChanged(dir); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridSortingTypeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class GridSortingTypeSideButton extends SideButton { private final IGrid grid; public GridSortingTypeSideButton(BaseScreen screen, IGrid grid) { super(screen); this.grid = grid; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.grid.sorting.type") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.grid.sorting.type." + grid.getSortingType()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { if (grid.getSortingType() == IGrid.SORTING_TYPE_LAST_MODIFIED) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 48, 48, 16, 16); } else { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, grid.getSortingType() * 16, 32, 16, 16); } } @Override public void onPress() { int type = grid.getSortingType(); if (type == IGrid.SORTING_TYPE_QUANTITY) { type = IGrid.SORTING_TYPE_NAME; } else if (type == IGrid.SORTING_TYPE_NAME) { if (grid.getGridType() == GridType.FLUID) { type = IGrid.SORTING_TYPE_LAST_MODIFIED; } else { type = IGrid.SORTING_TYPE_ID; } } else if (type == IGrid.SORTING_TYPE_ID) { type = IGrid.SORTING_TYPE_LAST_MODIFIED; } else if (type == IGrid.SORTING_TYPE_LAST_MODIFIED) { type = IGrid.SORTING_TYPE_QUANTITY; } else { type = IGrid.SORTING_TYPE_QUANTITY; } grid.onSortingTypeChanged(type); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/GridViewTypeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.container.GridContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class GridViewTypeSideButton extends SideButton { private final IGrid grid; public GridViewTypeSideButton(BaseScreen screen, IGrid grid) { super(screen); this.grid = grid; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.grid.view_type") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.grid.view_type." + grid.getViewType()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, (grid.getViewType() - (grid.getViewType() >= 3 ? 3 : 0)) * 16, 112, 16, 16); } @Override public void onPress() { int type = grid.getViewType(); if (type == IGrid.VIEW_TYPE_NORMAL) { type = IGrid.VIEW_TYPE_NON_CRAFTABLES; } else if (type == IGrid.VIEW_TYPE_NON_CRAFTABLES) { type = IGrid.VIEW_TYPE_CRAFTABLES; } else if (type == IGrid.VIEW_TYPE_CRAFTABLES) { type = IGrid.VIEW_TYPE_NORMAL; } grid.onViewTypeChanged(type); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/IoModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode; import com.refinedmods.refinedstorage.blockentity.DiskManipulatorBlockEntity; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.container.DiskManipulatorContainerMenu; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class IoModeSideButton extends SideButton { public IoModeSideButton(BaseScreen screen) { super(screen); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.iomode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.iomode." + (DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_INSERT ? "insert" : "extract")); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_EXTRACT ? 0 : 16, 160, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(DiskManipulatorBlockEntity.IO_MODE, DiskManipulatorBlockEntity.IO_MODE.getValue() == DiskManipulatorNetworkNode.IO_MODE_INSERT ? DiskManipulatorNetworkNode.IO_MODE_EXTRACT : DiskManipulatorNetworkNode.IO_MODE_INSERT); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/RedstoneModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class RedstoneModeSideButton extends SideButton { private final BlockEntitySynchronizationParameter parameter; public RedstoneModeSideButton(BaseScreen screen, BlockEntitySynchronizationParameter parameter) { super(screen); this.parameter = parameter; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.redstone_mode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.redstone_mode." + parameter.getValue()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, parameter.getValue() * 16, 0, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() + 1); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/SearchBoxModeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.api.network.grid.IGrid; import com.refinedmods.refinedstorage.integration.jei.JeiIntegration; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; import java.util.Arrays; import java.util.List; public abstract class SearchBoxModeSideButton extends SideButton { private static final List MODE_ROTATION = Arrays.asList( IGrid.SEARCH_BOX_MODE_NORMAL, IGrid.SEARCH_BOX_MODE_NORMAL_AUTOSELECTED, IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED, IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_AUTOSELECTED, IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY, IGrid.SEARCH_BOX_MODE_JEI_SYNCHRONIZED_2WAY_AUTOSELECTED, IGrid.SEARCH_BOX_MODE_NORMAL ); protected SearchBoxModeSideButton(BaseScreen screen) { super(screen); } private static int nextMode(int oldMode) { return MODE_ROTATION.get(MODE_ROTATION.indexOf(oldMode) + 1); } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.grid.search_box_mode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.grid.search_box_mode." + getSearchBoxMode()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { int mode = getSearchBoxMode(); graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, IGrid.isSearchBoxModeWithAutoselection(mode) ? 16 : 0, 96, 16, 16); } @Override public void onPress() { int mode = nextMode(getSearchBoxMode()); if (IGrid.doesSearchBoxModeUseJEI(mode) && !JeiIntegration.isLoaded()) { mode = IGrid.SEARCH_BOX_MODE_NORMAL; } setSearchBoxMode(mode); } protected abstract int getSearchBoxMode(); protected abstract void setSearchBoxMode(int mode); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/SideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.systems.RenderSystem; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.util.RenderUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.Button; import net.minecraft.network.chat.Component; import org.lwjgl.opengl.GL11; public abstract class SideButton extends Button { private static final Button.OnPress NO_ACTION = btn -> { }; private static final int WIDTH = 18; private static final int HEIGHT = 18; protected final BaseScreen screen; protected SideButton(BaseScreen screen) { super(Button.builder(Component.empty(), NO_ACTION).pos(-1, -1).size(WIDTH, HEIGHT)); this.screen = screen; } @Override public void renderWidget(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F); isHovered = RenderUtils.inBounds(getX(), getY(), width, height, mouseX, mouseY); graphics.blit(BaseScreen.ICONS_TEXTURE, getX(), getY(), 238, isHovered ? 35 : 16, WIDTH, HEIGHT); renderButtonIcon(graphics, getX() + 1, getY() + 1); if (isHovered) { RenderSystem.enableBlend(); RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 0.5f); graphics.blit(BaseScreen.ICONS_TEXTURE, getX(), getY(), 238, 54, WIDTH, HEIGHT); RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f); RenderSystem.disableBlend(); screen.renderTooltip(graphics, mouseX, mouseY, getSideButtonTooltip()); } } protected abstract void renderButtonIcon(GuiGraphics graphics, int x, int y); protected abstract String getSideButtonTooltip(); } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/TypeSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.refinedmods.refinedstorage.blockentity.config.IType; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import com.refinedmods.refinedstorage.screen.BaseScreen; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class TypeSideButton extends SideButton { private final BlockEntitySynchronizationParameter type; public TypeSideButton(BaseScreen screen, BlockEntitySynchronizationParameter type) { super(screen); this.type = type; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.type") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.type." + type.getValue()); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, 16 * type.getValue(), 128, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(type, type.getValue() == IType.ITEMS ? IType.FLUIDS : IType.ITEMS); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/screen/widget/sidebutton/WhitelistBlacklistSideButton.java ================================================ package com.refinedmods.refinedstorage.screen.widget.sidebutton; import com.mojang.blaze3d.vertex.PoseStack; import com.refinedmods.refinedstorage.screen.BaseScreen; import com.refinedmods.refinedstorage.blockentity.config.IWhitelistBlacklist; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationManager; import com.refinedmods.refinedstorage.blockentity.data.BlockEntitySynchronizationParameter; import net.minecraft.ChatFormatting; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.resources.language.I18n; public class WhitelistBlacklistSideButton extends SideButton { private final BlockEntitySynchronizationParameter parameter; public WhitelistBlacklistSideButton(BaseScreen screen, BlockEntitySynchronizationParameter parameter) { super(screen); this.parameter = parameter; } @Override protected String getSideButtonTooltip() { return I18n.get("sidebutton.refinedstorage.mode") + "\n" + ChatFormatting.GRAY + I18n.get("sidebutton.refinedstorage.mode." + (parameter.getValue() == IWhitelistBlacklist.WHITELIST ? "whitelist" : "blacklist")); } @Override protected void renderButtonIcon(GuiGraphics graphics, int x, int y) { graphics.blit(BaseScreen.ICONS_TEXTURE, x, y, parameter.getValue() == IWhitelistBlacklist.WHITELIST ? 0 : 16, 64, 16, 16); } @Override public void onPress() { BlockEntitySynchronizationManager.setParameter(parameter, parameter.getValue() == IWhitelistBlacklist.WHITELIST ? IWhitelistBlacklist.BLACKLIST : IWhitelistBlacklist.WHITELIST); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/setup/ClientSetup.java ================================================ package com.refinedmods.refinedstorage.setup; import com.refinedmods.refinedstorage.*; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.network.node.cover.CoverType; import com.refinedmods.refinedstorage.container.CrafterContainerMenu; import com.refinedmods.refinedstorage.container.CrafterManagerContainerMenu; import com.refinedmods.refinedstorage.container.slot.CrafterManagerSlot; import com.refinedmods.refinedstorage.item.property.ControllerItemPropertyGetter; import com.refinedmods.refinedstorage.item.property.NetworkItemPropertyGetter; import com.refinedmods.refinedstorage.item.property.SecurityCardItemPropertyGetter; import com.refinedmods.refinedstorage.render.BakedModelOverrideRegistry; import com.refinedmods.refinedstorage.render.blockentity.StorageMonitorBlockEntityRenderer; import com.refinedmods.refinedstorage.render.color.PatternItemColor; import com.refinedmods.refinedstorage.render.model.DiskDriveGeometryLoader; import com.refinedmods.refinedstorage.render.model.DiskManipulatorGeometryLoader; import com.refinedmods.refinedstorage.render.model.PortableGridGeometryLoader; import com.refinedmods.refinedstorage.render.model.baked.CableCoverBakedModel; import com.refinedmods.refinedstorage.render.model.baked.CableCoverItemBakedModel; import com.refinedmods.refinedstorage.render.model.baked.PatternBakedModel; import com.refinedmods.refinedstorage.render.resourcepack.ResourcePackListener; import com.refinedmods.refinedstorage.screen.*; import com.refinedmods.refinedstorage.screen.factory.CrafterManagerScreenFactory; import com.refinedmods.refinedstorage.screen.factory.GridScreenFactory; import com.refinedmods.refinedstorage.util.ColorMap; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.renderer.blockentity.BlockEntityRenderers; import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; import net.neoforged.neoforge.client.event.ModelEvent; import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; import net.neoforged.neoforge.client.event.RegisterKeyMappingsEvent; import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.event.AddReloadListenerEvent; import java.util.Arrays; import java.util.function.BiConsumer; public final class ClientSetup { private static final ResourceLocation DISK_RESOURCE = new ResourceLocation(RS.ID + ":block/disks/disk"); private static final ResourceLocation DISK_NEAR_CAPACITY_RESOURCE = new ResourceLocation(RS.ID + ":block/disks/disk_near_capacity"); private static final ResourceLocation DISK_FULL_RESOURCE = new ResourceLocation(RS.ID + ":block/disks/disk_full"); private static final ResourceLocation DISK_DISCONNECTED_RESOURCE = new ResourceLocation(RS.ID + ":block/disks/disk_disconnected"); private static final ResourceLocation CONNECTED = new ResourceLocation(RS.ID, "connected"); private static final BakedModelOverrideRegistry BAKED_MODEL_OVERRIDE_REGISTRY = new BakedModelOverrideRegistry(); private ClientSetup() { } @SubscribeEvent public static void onClientSetup(FMLClientSetupEvent e) { NeoForge.EVENT_BUS.register(new KeyInputListener()); registerBakedModelOverrides(); registerPatternRenderHandlers(); BlockEntityRenderers.register(RSBlockEntities.STORAGE_MONITOR.get(), ctx -> new StorageMonitorBlockEntityRenderer()); // ItemProperties isn't thread safe e.enqueueWork(() -> { ItemProperties.register(RSItems.SECURITY_CARD.get(), new ResourceLocation(RS.ID, "active"), new SecurityCardItemPropertyGetter()); RSItems.CONTROLLER.values().forEach(controller -> ItemProperties.register(controller.get(), new ResourceLocation(RS.ID, "energy_type"), new ControllerItemPropertyGetter())); RSItems.CREATIVE_CONTROLLER.values().forEach(controller -> ItemProperties.register(controller.get(), new ResourceLocation(RS.ID, "energy_type"), new ControllerItemPropertyGetter())); ItemProperties.register(RSItems.WIRELESS_CRAFTING_MONITOR.get(), CONNECTED, new NetworkItemPropertyGetter()); ItemProperties.register(RSItems.CREATIVE_WIRELESS_CRAFTING_MONITOR.get(), CONNECTED, new NetworkItemPropertyGetter()); ItemProperties.register(RSItems.WIRELESS_GRID.get(), CONNECTED, new NetworkItemPropertyGetter()); ItemProperties.register(RSItems.CREATIVE_WIRELESS_GRID.get(), CONNECTED, new NetworkItemPropertyGetter()); ItemProperties.register(RSItems.WIRELESS_FLUID_GRID.get(), CONNECTED, new NetworkItemPropertyGetter()); ItemProperties.register(RSItems.CREATIVE_WIRELESS_FLUID_GRID.get(), CONNECTED, new NetworkItemPropertyGetter()); }); } @SubscribeEvent public static void registerMenuScreens(RegisterMenuScreensEvent e) { e.register(RSContainerMenus.FILTER.get(), FilterScreen::new); e.register(RSContainerMenus.CONTROLLER.get(), ControllerScreen::new); e.register(RSContainerMenus.DISK_DRIVE.get(), DiskDriveScreen::new); e.register(RSContainerMenus.GRID.get(), new GridScreenFactory()); e.register(RSContainerMenus.STORAGE_BLOCK.get(), StorageBlockScreen::new); e.register(RSContainerMenus.FLUID_STORAGE_BLOCK.get(), FluidStorageBlockScreen::new); e.register(RSContainerMenus.EXTERNAL_STORAGE.get(), ExternalStorageScreen::new); e.register(RSContainerMenus.IMPORTER.get(), ImporterScreen::new); e.register(RSContainerMenus.EXPORTER.get(), ExporterScreen::new); e.register(RSContainerMenus.NETWORK_TRANSMITTER.get(), NetworkTransmitterScreen::new); e.register(RSContainerMenus.RELAY.get(), RelayScreen::new); e.register(RSContainerMenus.DETECTOR.get(), DetectorScreen::new); e.register(RSContainerMenus.SECURITY_MANAGER.get(), SecurityManagerScreen::new); e.register(RSContainerMenus.INTERFACE.get(), InterfaceScreen::new); e.register(RSContainerMenus.FLUID_INTERFACE.get(), FluidInterfaceScreen::new); e.register(RSContainerMenus.WIRELESS_TRANSMITTER.get(), WirelessTransmitterScreen::new); e.register(RSContainerMenus.STORAGE_MONITOR.get(), StorageMonitorScreen::new); e.register(RSContainerMenus.CONSTRUCTOR.get(), ConstructorScreen::new); e.register(RSContainerMenus.DESTRUCTOR.get(), DestructorScreen::new); e.register(RSContainerMenus.DISK_MANIPULATOR.get(), DiskManipulatorScreen::new); e.register(RSContainerMenus.CRAFTER.get(), CrafterScreen::new); e.register(RSContainerMenus.CRAFTER_MANAGER.get(), new CrafterManagerScreenFactory()); e.register(RSContainerMenus.CRAFTING_MONITOR.get(), CraftingMonitorScreen::new); e.register(RSContainerMenus.WIRELESS_CRAFTING_MONITOR.get(), CraftingMonitorScreen::new); } private static void registerPatternRenderHandlers() { API.instance().addPatternRenderHandler(pattern -> Screen.hasShiftDown()); API.instance().addPatternRenderHandler(pattern -> { AbstractContainerMenu container = Minecraft.getInstance().player.containerMenu; if (container instanceof CrafterManagerContainerMenu) { for (Slot slot : container.slots) { if (slot instanceof CrafterManagerSlot && slot.getItem() == pattern) { return true; } } } return false; }); API.instance().addPatternRenderHandler(pattern -> { AbstractContainerMenu container = Minecraft.getInstance().player.containerMenu; if (container instanceof CrafterContainerMenu) { for (int i = 0; i < 9; ++i) { if (container.getSlot(i).getItem() == pattern) { return true; } } } return false; }); } private static void registerBakedModelOverrides() { BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "cable"), (base, registry) -> new CableCoverBakedModel(base)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "exporter"), (base, registry) -> new CableCoverBakedModel(base)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "importer"), (base, registry) -> new CableCoverBakedModel(base)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "external_storage"), (base, registry) -> new CableCoverBakedModel(base)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "cover"), (base, registry) -> new CableCoverItemBakedModel(ItemStack.EMPTY, CoverType.NORMAL)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "hollow_cover"), (base, registry) -> new CableCoverItemBakedModel(ItemStack.EMPTY, CoverType.HOLLOW)); BAKED_MODEL_OVERRIDE_REGISTRY.add(new ResourceLocation(RS.ID, "pattern"), (base, registry) -> new PatternBakedModel(base)); } @SubscribeEvent public static void onRegisterColorBindings(RegisterColorHandlersEvent.Item e) { e.register(new PatternItemColor(), RSItems.PATTERN.get()); } @SubscribeEvent public static void onRegisterKeymappings(RegisterKeyMappingsEvent e) { e.register(RSKeyBindings.FOCUS_SEARCH_BAR); e.register(RSKeyBindings.CLEAR_GRID_CRAFTING_MATRIX); e.register(RSKeyBindings.OPEN_WIRELESS_GRID); e.register(RSKeyBindings.OPEN_WIRELESS_FLUID_GRID); e.register(RSKeyBindings.OPEN_WIRELESS_CRAFTING_MONITOR); e.register(RSKeyBindings.OPEN_PORTABLE_GRID); } @SubscribeEvent public static void addReloadListener(AddReloadListenerEvent event) { event.addListener(new ResourcePackListener()); } @SubscribeEvent public static void onRegisterAdditionalModels(ModelEvent.RegisterAdditional e) { e.register(DISK_RESOURCE); e.register(DISK_NEAR_CAPACITY_RESOURCE); e.register(DISK_FULL_RESOURCE); e.register(DISK_DISCONNECTED_RESOURCE); e.register(new ResourceLocation(RS.ID + ":block/disk_manipulator/disconnected")); for (DyeColor color : DyeColor.values()) { e.register(new ResourceLocation(RS.ID + ":block/disk_manipulator/" + color)); } } @SubscribeEvent public static void onModelBake(ModelEvent.ModifyBakingResult e) { for (ResourceLocation id : e.getModels().keySet()) { BakedModelOverrideRegistry.BakedModelOverrideFactory factory = BAKED_MODEL_OVERRIDE_REGISTRY.get(new ResourceLocation(id.getNamespace(), id.getPath())); if (factory != null) { e.getModels().put(id, factory.create(e.getModels().get(id), e.getModels())); } } } @SubscribeEvent public static void onRegisterModelGeometry(final ModelEvent.RegisterGeometryLoaders e) { e.register(new ResourceLocation(RS.ID, "disk_drive"), new DiskDriveGeometryLoader()); e.register(new ResourceLocation(RS.ID, "disk_manipulator"), new DiskManipulatorGeometryLoader()); e.register(new ResourceLocation(RS.ID, "portable_grid"), new PortableGridGeometryLoader()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/setup/CommonSetup.java ================================================ package com.refinedmods.refinedstorage.setup; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlockEntities; import com.refinedmods.refinedstorage.RSCreativeModeTabItems; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.RSLootFunctions; import com.refinedmods.refinedstorage.api.network.grid.GridType; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ErrorCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.FluidCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.craftingmonitor.ItemCraftingMonitorElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ErrorCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.FluidCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.preview.ItemCraftingPreviewElement; import com.refinedmods.refinedstorage.apiimpl.autocrafting.task.v6.CraftingTaskFactory; import com.refinedmods.refinedstorage.apiimpl.network.NetworkListener; import com.refinedmods.refinedstorage.apiimpl.network.NetworkNodeListener; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.GridBlockGridFactory; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridBlockGridFactory; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.PortableGridGridFactory; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessFluidGridGridFactory; import com.refinedmods.refinedstorage.apiimpl.network.grid.factory.WirelessGridGridFactory; import com.refinedmods.refinedstorage.apiimpl.network.node.CableNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.ConstructorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterManagerNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.CrafterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.CraftingMonitorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.DestructorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.DetectorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.ExporterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.ExternalStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.FluidInterfaceNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.GridNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.ImporterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.InterfaceNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkReceiverNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.NetworkTransmitterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.RelayNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.SecurityManagerNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.StorageMonitorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.WirelessTransmitterNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.diskdrive.DiskDriveNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.diskmanipulator.DiskManipulatorNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.FluidStorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.network.node.storage.StorageNetworkNode; import com.refinedmods.refinedstorage.apiimpl.storage.FluidStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.ItemStorageType; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.FluidStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.disk.factory.ItemStorageDiskFactory; import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.FluidExternalStorageProvider; import com.refinedmods.refinedstorage.apiimpl.storage.externalstorage.ItemExternalStorageProvider; import com.refinedmods.refinedstorage.block.BlockListener; import com.refinedmods.refinedstorage.blockentity.CrafterBlockEntity; import com.refinedmods.refinedstorage.integration.craftingtweaks.CraftingTweaksIntegration; import com.refinedmods.refinedstorage.integration.inventorysorter.InventorySorterIntegration; import net.minecraft.core.registries.Registries; import net.minecraft.nbt.CompoundTag; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.common.NeoForge; import net.neoforged.neoforge.network.event.RegisterPayloadHandlerEvent; import net.neoforged.neoforge.network.registration.IPayloadRegistrar; import net.neoforged.neoforge.registries.RegisterEvent; public final class CommonSetup { private CommonSetup() { } @SubscribeEvent public static void onRegister(final RegisterEvent e) { e.register(Registries.LOOT_FUNCTION_TYPE, helper -> RSLootFunctions.register()); e.register(Registries.CREATIVE_MODE_TAB, RSCreativeModeTabItems::register); } @SubscribeEvent public static void onCommonSetup(FMLCommonSetupEvent e) { NeoForge.EVENT_BUS.register(new NetworkNodeListener()); NeoForge.EVENT_BUS.register(new NetworkListener()); NeoForge.EVENT_BUS.register(new BlockListener()); API.instance().getStorageDiskRegistry().add(ItemStorageDiskFactory.ID, new ItemStorageDiskFactory()); API.instance().getStorageDiskRegistry().add(FluidStorageDiskFactory.ID, new FluidStorageDiskFactory()); API.instance().getNetworkNodeRegistry().add(DiskDriveNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new DiskDriveNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(CableNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CableNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(GridNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.NORMAL))); API.instance().getNetworkNodeRegistry().add(GridNetworkNode.CRAFTING_ID, (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.CRAFTING))); API.instance().getNetworkNodeRegistry().add(GridNetworkNode.PATTERN_ID, (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.PATTERN))); API.instance().getNetworkNodeRegistry().add(GridNetworkNode.FLUID_ID, (tag, world, pos) -> readAndReturn(tag, new GridNetworkNode(world, pos, GridType.FLUID))); API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.ONE_K_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.ONE_K))); API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.FOUR_K_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.FOUR_K))); API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.SIXTEEN_K_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.SIXTEEN_K))); API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.SIXTY_FOUR_K_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.SIXTY_FOUR_K))); API.instance().getNetworkNodeRegistry().add(StorageNetworkNode.CREATIVE_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new StorageNetworkNode(world, pos, ItemStorageType.CREATIVE))); API.instance().getNetworkNodeRegistry().add(FluidStorageNetworkNode.SIXTY_FOUR_K_FLUID_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new FluidStorageNetworkNode(world, pos, FluidStorageType.SIXTY_FOUR_K))); API.instance().getNetworkNodeRegistry() .add(FluidStorageNetworkNode.TWO_HUNDRED_FIFTY_SIX_K_FLUID_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new FluidStorageNetworkNode(world, pos, FluidStorageType.TWO_HUNDRED_FIFTY_SIX_K))); API.instance().getNetworkNodeRegistry() .add(FluidStorageNetworkNode.THOUSAND_TWENTY_FOUR_K_FLUID_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new FluidStorageNetworkNode(world, pos, FluidStorageType.THOUSAND_TWENTY_FOUR_K))); API.instance().getNetworkNodeRegistry() .add(FluidStorageNetworkNode.FOUR_THOUSAND_NINETY_SIX_K_FLUID_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new FluidStorageNetworkNode(world, pos, FluidStorageType.FOUR_THOUSAND_NINETY_SIX_K))); API.instance().getNetworkNodeRegistry().add(FluidStorageNetworkNode.CREATIVE_FLUID_STORAGE_BLOCK_ID, (tag, world, pos) -> readAndReturn(tag, new FluidStorageNetworkNode(world, pos, FluidStorageType.CREATIVE))); API.instance().getNetworkNodeRegistry().add(ExternalStorageNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ExternalStorageNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(ImporterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ImporterNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(ExporterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ExporterNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(NetworkReceiverNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new NetworkReceiverNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(NetworkTransmitterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new NetworkTransmitterNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(RelayNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new RelayNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(DetectorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new DetectorNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(SecurityManagerNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new SecurityManagerNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(InterfaceNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new InterfaceNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(FluidInterfaceNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new FluidInterfaceNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(WirelessTransmitterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new WirelessTransmitterNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(StorageMonitorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new StorageMonitorNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(ConstructorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new ConstructorNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(DestructorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new DestructorNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(DiskManipulatorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new DiskManipulatorNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry() .add(CrafterNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CrafterNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(CrafterManagerNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CrafterManagerNetworkNode(world, pos))); API.instance().getNetworkNodeRegistry().add(CraftingMonitorNetworkNode.ID, (tag, world, pos) -> readAndReturn(tag, new CraftingMonitorNetworkNode(world, pos))); API.instance().getGridManager().add(GridBlockGridFactory.ID, new GridBlockGridFactory()); API.instance().getGridManager().add(WirelessGridGridFactory.ID, new WirelessGridGridFactory()); API.instance().getGridManager().add(WirelessFluidGridGridFactory.ID, new WirelessFluidGridGridFactory()); API.instance().getGridManager().add(PortableGridGridFactory.ID, new PortableGridGridFactory()); API.instance().getGridManager().add(PortableGridBlockGridFactory.ID, new PortableGridBlockGridFactory()); API.instance().addExternalStorageProvider(StorageType.ITEM, new ItemExternalStorageProvider()); API.instance().addExternalStorageProvider(StorageType.FLUID, new FluidExternalStorageProvider()); API.instance().getCraftingPreviewElementRegistry() .add(ItemCraftingPreviewElement.ID, ItemCraftingPreviewElement::read); API.instance().getCraftingPreviewElementRegistry() .add(FluidCraftingPreviewElement.ID, FluidCraftingPreviewElement::read); API.instance().getCraftingPreviewElementRegistry() .add(ErrorCraftingPreviewElement.ID, ErrorCraftingPreviewElement::read); API.instance().getCraftingMonitorElementRegistry() .add(ItemCraftingMonitorElement.ID, ItemCraftingMonitorElement::read); API.instance().getCraftingMonitorElementRegistry() .add(FluidCraftingMonitorElement.ID, FluidCraftingMonitorElement::read); API.instance().getCraftingMonitorElementRegistry() .add(ErrorCraftingMonitorElement.ID, ErrorCraftingMonitorElement::read); API.instance().getCraftingTaskRegistry().add(CraftingTaskFactory.ID, new CraftingTaskFactory()); if (CraftingTweaksIntegration.isLoaded()) { CraftingTweaksIntegration.register(); } if (InventorySorterIntegration.isLoaded()) { InventorySorterIntegration.register(); } } private static INetworkNode readAndReturn(CompoundTag tag, NetworkNode node) { node.read(tag); return node; } @SubscribeEvent public static void onRegisterNetworkPackets(final RegisterPayloadHandlerEvent event) { final IPayloadRegistrar registrar = event.registrar(RS.ID); RS.NETWORK_HANDLER.register(registrar); } @SubscribeEvent public static void onRegisterCapabilities(final RegisterCapabilitiesEvent e) { e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.CRAFTER.get(), CrafterBlockEntity::getPatterns ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.DISK_MANIPULATOR.get(), (be, side) -> be.getNode().getDisks() ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.FLUID_INTERFACE.get(), (be, side) -> be.getNode().getIn() ); e.registerBlockEntity( Capabilities.FluidHandler.BLOCK, RSBlockEntities.FLUID_INTERFACE.get(), (be, side) -> be.getNode().getTank() ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.INTERFACE.get(), (be, side) -> be.getNode().getItems() ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.DISK_DRIVE.get(), (be, side) -> be.getNode().getDisks() ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.NETWORK_TRANSMITTER.get(), (be, side) -> be.getNode().getNetworkCard() ); e.registerBlockEntity( Capabilities.EnergyStorage.BLOCK, RSBlockEntities.CONTROLLER.get(), (be, side) -> be.getNetwork().getEnergyStorage() ); e.registerBlockEntity( Capabilities.ItemHandler.BLOCK, RSBlockEntities.GRID.get(), (be, side) -> be.getInventory() ); e.registerBlockEntity( Capabilities.EnergyStorage.BLOCK, RSBlockEntities.PORTABLE_GRID.get(), (be, side) -> be.getEnergyStorage() ); RSItems.CONTROLLER.values().forEach(value -> e.registerItem( Capabilities.EnergyStorage.ITEM, (stack, ctx) -> value.get().createEnergyStorage(stack), value.get() )); e.registerItem( Capabilities.EnergyStorage.ITEM, (stack, ctx) -> RSItems.PORTABLE_GRID.get().createEnergyStorage(stack), RSItems.PORTABLE_GRID.get() ); e.registerItem( Capabilities.EnergyStorage.ITEM, (stack, ctx) -> RSItems.WIRELESS_GRID.get().createEnergyStorage(stack), RSItems.WIRELESS_GRID.get() ); e.registerItem( Capabilities.EnergyStorage.ITEM, (stack, ctx) -> RSItems.WIRELESS_FLUID_GRID.get().createEnergyStorage(stack), RSItems.WIRELESS_FLUID_GRID.get() ); e.registerItem( Capabilities.EnergyStorage.ITEM, (stack, ctx) -> RSItems.WIRELESS_CRAFTING_MONITOR.get().createEnergyStorage(stack), RSItems.WIRELESS_CRAFTING_MONITOR.get() ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/setup/ServerSetup.java ================================================ package com.refinedmods.refinedstorage.setup; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.command.disk.CreateDiskCommand; import com.refinedmods.refinedstorage.command.disk.ListDiskCommand; import com.refinedmods.refinedstorage.command.network.GetNetworkCommand; import com.refinedmods.refinedstorage.command.network.ListNetworkCommand; import com.refinedmods.refinedstorage.command.pattern.PatternDumpCommand; import net.minecraft.commands.Commands; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.neoforge.event.RegisterCommandsEvent; public class ServerSetup { @SubscribeEvent public void onRegisterCommands(RegisterCommandsEvent e) { e.getDispatcher().register(Commands.literal(RS.ID) .then(Commands.literal("pattern") .then(PatternDumpCommand.register())) .then(Commands.literal("disk") .then(CreateDiskCommand.register()) .then(ListDiskCommand.register())) .then(Commands.literal("network") .then(GetNetworkCommand.register()) .then(ListNetworkCommand.register()))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/AccessTypeUtils.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.api.storage.AccessType; import net.minecraft.nbt.CompoundTag; public final class AccessTypeUtils { private static final String NBT_ACCESS_TYPE = "AccessType"; private AccessTypeUtils() { } public static void writeAccessType(CompoundTag tag, AccessType type) { tag.putInt(NBT_ACCESS_TYPE, type.getId()); } public static AccessType readAccessType(CompoundTag tag) { return tag.contains(NBT_ACCESS_TYPE) ? getAccessType(tag.getInt(NBT_ACCESS_TYPE)) : AccessType.INSERT_EXTRACT; } public static AccessType getAccessType(int id) { for (AccessType type : AccessType.values()) { if (type.getId() == id) { return type; } } return AccessType.INSERT_EXTRACT; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/BlockColorMap.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSBlocks; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.block.BlockDirection; import com.refinedmods.refinedstorage.block.NetworkNodeBlock; import java.util.List; import java.util.function.Supplier; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; public class BlockColorMap extends ColorMap { public BlockColorMap(DeferredRegister registry) { super(registry); } public BlockColorMap(DeferredRegister registry, List lateRegistration) { super(registry, lateRegistration); } public Block[] getBlocks() { return map.values().stream().map(DeferredHolder::get).toArray(Block[]::new); } public void registerBlocks(String name, Supplier blockFactory) { for (DyeColor color : DyeColor.values()) { String prefix = color != DEFAULT_COLOR ? color + "_" : ""; DeferredHolder block = registry.register(prefix + name, blockFactory); map.put(color, block); RSBlocks.COLORED_BLOCKS.add(block); } RSBlocks.COLORED_BLOCK_TAGS.put( BlockTags.create(new ResourceLocation(RS.ID, get(DEFAULT_COLOR).getId().getPath())), this ); } public InteractionResult changeBlockColor(BlockState state, ItemStack heldItem, Level level, BlockPos pos, Player player) { DyeColor color = DyeColor.getColor(heldItem); if (color == null || state.getBlock().equals(map.get(color).get())) { return InteractionResult.PASS; } return setBlockState(getNewState((DeferredHolder) map.get(color), state), heldItem, level, pos, player); } private BlockState getNewState(DeferredHolder block, BlockState state) { BlockState newState = block.get().defaultBlockState(); if (((NetworkNodeBlock) block.get()).hasConnectedState()) { newState = newState.setValue(NetworkNodeBlock.CONNECTED, state.getValue(NetworkNodeBlock.CONNECTED)); } if (block.get().getDirection() != BlockDirection.NONE) { newState = newState.setValue(block.get().getDirection().getProperty(), state.getValue(block.get().getDirection().getProperty())); } return newState; } public InteractionResult setBlockState(BlockState newState, ItemStack heldItem, Level level, BlockPos pos, Player player) { if (!level.isClientSide) { level.setBlockAndUpdate(pos, newState); if (((ServerPlayer) player).gameMode.getGameModeForPlayer() != GameType.CREATIVE) { heldItem.shrink(1); } } return InteractionResult.SUCCESS; } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/BlockUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.network.chat.Component; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockBehaviour; public final class BlockUtils { public static final BlockBehaviour.Properties DEFAULT_ROCK_PROPERTIES = BlockBehaviour.Properties.of().strength(0.5F, 6.0F).sound(SoundType.STONE); public static final BlockBehaviour.Properties DEFAULT_GLASS_PROPERTIES = BlockBehaviour.Properties.of().sound(SoundType.GLASS).strength(0.35F); private BlockUtils() { } // Block#getTranslatedName is client only public static Component getBlockTranslation(Block block) { return Component.translatable(block.getDescriptionId()); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/CollisionUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.VoxelShape; public final class CollisionUtils { private CollisionUtils() { } public static boolean isInBounds(VoxelShape shape, BlockPos pos, Vec3 hit) { AABB aabb = shape.bounds().move(pos); return hit.x >= aabb.minX && hit.x <= aabb.maxX && hit.y >= aabb.minY && hit.y <= aabb.maxY && hit.z >= aabb.minZ && hit.z <= aabb.maxZ; } public static AABB getBounds(int fromX, int fromY, int fromZ, int toX, int toY, int toZ) { return new AABB((float) fromX / 16F, (float) fromY / 16F, (float) fromZ / 16F, (float) toX / 16F, (float) toY / 16F, (float) toZ / 16F); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/ColorMap.java ================================================ package com.refinedmods.refinedstorage.util; import java.util.Collection; import java.util.EnumMap; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; import net.minecraft.world.item.DyeColor; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; public class ColorMap { public static final DyeColor DEFAULT_COLOR = DyeColor.LIGHT_BLUE; protected final Map> map = new EnumMap<>(DyeColor.class); private final Map colorByBlock = new HashMap<>(); protected final DeferredRegister registry; protected List lateRegistration; public ColorMap(DeferredRegister registry) { this.registry = registry; } public ColorMap(DeferredRegister registry, List lateRegistration) { this.registry = registry; this.lateRegistration = lateRegistration; } public DeferredHolder get(DyeColor color) { return map.get(color); } public DyeColor getColorFromObject(T object) { if (colorByBlock.isEmpty()) { map.forEach(((dyeColor, registryObject) -> colorByBlock.put(registryObject.get(), dyeColor))); } return colorByBlock.get(object); } public Collection> values() { return map.values(); } public void put(DyeColor color, DeferredHolder object) { map.put(color, object); } public void forEach(BiConsumer> consumer) { map.forEach(consumer); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/DirectionUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.LivingEntity; public final class DirectionUtils { private DirectionUtils() { } public static Direction getFacingFromEntity(BlockPos clickedBlock, LivingEntity entity) { return Direction.getNearest( (float) (entity.getX() - clickedBlock.getX()), (float) (entity.getY() - clickedBlock.getY()), (float) (entity.getZ() - clickedBlock.getZ()) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/ItemColorMap.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.RS; import com.refinedmods.refinedstorage.RSItems; import com.refinedmods.refinedstorage.block.BaseBlock; import com.refinedmods.refinedstorage.item.blockitem.ColoredBlockItem; import java.util.List; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.ItemTags; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.neoforged.neoforge.registries.DeferredHolder; import net.neoforged.neoforge.registries.DeferredRegister; public class ItemColorMap extends ColorMap { public ItemColorMap(DeferredRegister registry) { super(registry); } public ItemColorMap(DeferredRegister registry, List lateRegistration) { super(registry, lateRegistration); } public void registerItemsFromBlocks(ColorMap blockMap) { DeferredHolder originalBlock = blockMap.get(DEFAULT_COLOR); map.put(DEFAULT_COLOR, registerBlockItemFor(originalBlock, DEFAULT_COLOR, originalBlock)); lateRegistration.add(() -> blockMap.forEach((color, block) -> { if (color != DEFAULT_COLOR) { map.put(color, registerBlockItemFor(block, color, originalBlock)); } })); RSItems.COLORED_ITEM_TAGS.put( ItemTags.create(new ResourceLocation(RS.ID, blockMap.get(DEFAULT_COLOR).getId().getPath())), this ); } private DeferredHolder registerBlockItemFor( DeferredHolder block, DyeColor color, DeferredHolder translationBlock ) { return registry.register( block.getId().getPath(), () -> new ColoredBlockItem( block.get(), new Item.Properties(), color, BlockUtils.getBlockTranslation(translationBlock.get()) ) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/ItemStackKey.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.world.item.ItemStack; public final class ItemStackKey { private final ItemStack stack; public ItemStackKey(ItemStack stack) { this.stack = stack; } public ItemStack getStack() { return stack; } @Override public boolean equals(Object other) { return other instanceof ItemStackKey && API.instance().getComparer().isEqualNoQuantity(stack, ((ItemStackKey) other).stack); } @Override public int hashCode() { return API.instance().getItemStackHashCode(stack); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/LevelUtils.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.render.Styles; import java.util.Optional; import java.util.UUID; import javax.annotation.Nullable; import com.mojang.authlib.GameProfile; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.players.GameProfileCache; import net.minecraft.world.Container; import net.minecraft.world.WorldlyContainer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.ClipContext; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.common.util.FakePlayer; import net.neoforged.neoforge.common.util.FakePlayerFactory; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.wrapper.InvWrapper; import net.neoforged.neoforge.items.wrapper.SidedInvWrapper; public final class LevelUtils { private LevelUtils() { } public static void updateBlock(@Nullable Level level, BlockPos pos) { if (level != null && level.isLoaded(pos)) { BlockState state = level.getBlockState(pos); level.sendBlockUpdated(pos, state, state, 1 | 2); } } public static IItemHandler getItemHandler(@Nullable Level level, BlockPos pos, Direction side) { if (level == null) { return null; } IItemHandler handler = level.getCapability(Capabilities.ItemHandler.BLOCK, pos, side); if (handler == null) { if (level instanceof WorldlyContainer) { handler = new SidedInvWrapper((WorldlyContainer) level, side); } else if (level instanceof Container) { handler = new InvWrapper((Container) level); } } return handler; } public static IFluidHandler getFluidHandler(@Nullable Level level, BlockPos pos, Direction side) { if (level == null) { return null; } return level.getCapability(Capabilities.FluidHandler.BLOCK, pos, side); } public static FakePlayer getFakePlayer(ServerLevel level, @Nullable UUID owner) { if (owner != null) { GameProfileCache profileCache = level.getServer().getProfileCache(); Optional profile = profileCache.get(owner); if (profile.isPresent()) { return FakePlayerFactory.get(level, profile.get()); } } return FakePlayerFactory.getMinecraft(level); } public static void sendNoPermissionMessage(Player player) { player.sendSystemMessage( Component.translatable("misc.refinedstorage.security.no_permission").setStyle(Styles.RED)); } public static HitResult rayTracePlayer(Level level, Player player) { double reachDistance = player.getBlockReach(); Vec3 base = player.getEyePosition(1.0F); Vec3 look = player.getLookAngle(); Vec3 target = base.add(look.x * reachDistance, look.y * reachDistance, look.z * reachDistance); return level.clip(new ClipContext(base, target, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player)); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/NetworkUtils.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.api.network.INetwork; import com.refinedmods.refinedstorage.api.network.node.INetworkNode; import com.refinedmods.refinedstorage.api.network.node.INetworkNodeProxy; import com.refinedmods.refinedstorage.api.network.security.Permission; import com.refinedmods.refinedstorage.api.util.Action; import com.refinedmods.refinedstorage.apiimpl.API; import net.minecraft.core.BlockPos; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import javax.annotation.Nullable; import java.util.function.Consumer; public final class NetworkUtils { private NetworkUtils() { } @Nullable public static INetworkNode getNodeFromBlockEntity(@Nullable BlockEntity blockEntity) { if (blockEntity instanceof INetworkNodeProxy proxy) { return proxy.getNode(); } return null; } @Nullable public static INetwork getNetworkFromNode(@Nullable INetworkNode node) { if (node != null) { return node.getNetwork(); } return null; } public static InteractionResult attemptModify(Level level, BlockPos pos, Player player, Runnable action) { return attempt(level, pos, player, action, Permission.MODIFY); } public static InteractionResult attempt(Level level, BlockPos pos, Player player, Runnable action, Permission... permissionsRequired) { if (level.isClientSide) { return InteractionResult.SUCCESS; } INetwork network = getNetworkFromNode(getNodeFromBlockEntity(level.getBlockEntity(pos))); if (network != null) { for (Permission permission : permissionsRequired) { if (!network.getSecurityManager().hasPermission(permission, player)) { LevelUtils.sendNoPermissionMessage(player); return InteractionResult.SUCCESS; } } } action.run(); return InteractionResult.SUCCESS; } public static void extractBucketFromPlayerInventoryOrNetwork(Player player, INetwork network, Consumer onBucketFound) { for (int i = 0; i < player.getInventory().getContainerSize(); ++i) { ItemStack slot = player.getInventory().getItem(i); if (API.instance().getComparer().isEqualNoQuantity(StackUtils.EMPTY_BUCKET, slot)) { player.getInventory().removeItem(i, 1); onBucketFound.accept(StackUtils.EMPTY_BUCKET.copy()); return; } } ItemStack fromNetwork = network.extractItem(StackUtils.EMPTY_BUCKET, 1, Action.PERFORM); if (!fromNetwork.isEmpty()) { onBucketFound.accept(fromNetwork); } } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/PacketBufferUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.network.FriendlyByteBuf; public final class PacketBufferUtils { private PacketBufferUtils() { } // @Volatile: From PacketBuffer#readUtf, this exists because SideOnly public static String readString(FriendlyByteBuf buffer) { return buffer.readUtf(32767); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/PlayerUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Inventory; public class PlayerUtils { public static void updateHeldItems(ServerPlayer player) { int mainHandSlot = player.getInventory().selected; int offHandSlot = Inventory.SLOT_OFFHAND; //See ClientPlayNetHandler#HandleSetSlot for the awful vanilla code that makes this necessary // -2 as that directly sets the inventory slots player.connection.send(new ClientboundContainerSetSlotPacket(-2, player.containerMenu.incrementStateId(), mainHandSlot, player.getInventory().getItem(mainHandSlot))); player.connection.send(new ClientboundContainerSetSlotPacket(-2, player.containerMenu.incrementStateId(), offHandSlot, player.getInventory().getItem(offHandSlot))); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/RenderUtils.java ================================================ package com.refinedmods.refinedstorage.util; import com.google.common.collect.ImmutableMap; import com.refinedmods.refinedstorage.api.util.IComparer; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.render.Styles; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.ItemTransform; import net.minecraft.client.renderer.block.model.ItemTransforms; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.core.Direction; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.level.block.state.BlockState; import net.neoforged.neoforge.client.model.data.ModelData; import net.neoforged.neoforge.fluids.FluidStack; import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.HashSet; import java.util.List; import java.util.Set; public final class RenderUtils { private RenderUtils() { } private static Vector3f getRotationVector(Direction direction) { return switch (direction) { case NORTH -> new Vector3f(0, 0, 0); case EAST -> new Vector3f(0, -90, 0); case SOUTH -> new Vector3f(0, 180, 0); case WEST -> new Vector3f(0, 90, 0); case UP -> new Vector3f(90, 0, 180); case DOWN -> new Vector3f(-90, 0, 0); }; } public static Quaternionf getQuaternion(Direction direction) { Vector3f vec = getRotationVector(direction); return new Quaternionf().rotateXYZ( vec.x() * Mth.DEG_TO_RAD, vec.y() * Mth.DEG_TO_RAD, vec.z() * Mth.DEG_TO_RAD ); } public static String shorten(String text, int length) { if (text.length() > length) { text = text.substring(0, length) + "..."; } return text; } public static int getOffsetOnScale(int pos, float scale) { float multiplier = (pos / scale); return (int) multiplier; } public static void addCombinedItemsToTooltip(List tooltip, boolean displayAmount, List stacks) { Set combinedIndices = new HashSet<>(); for (int i = 0; i < stacks.size(); ++i) { if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) { ItemStack stack = stacks.get(i); MutableComponent data = stack.getHoverName().plainCopy(); int amount = stack.getCount(); for (int j = i + 1; j < stacks.size(); ++j) { if (API.instance().getComparer().isEqual(stack, stacks.get(j))) { amount += stacks.get(j).getCount(); combinedIndices.add(j); } } if (displayAmount) { data = Component.literal(amount + "x ").append(data); } tooltip.add(data.setStyle(Styles.GRAY)); } } } public static void addCombinedFluidsToTooltip(List tooltip, boolean displayMb, List stacks) { Set combinedIndices = new HashSet<>(); for (int i = 0; i < stacks.size(); ++i) { if (!stacks.get(i).isEmpty() && !combinedIndices.contains(i)) { FluidStack stack = stacks.get(i); MutableComponent data = stack.getDisplayName().plainCopy(); int amount = stack.getAmount(); for (int j = i + 1; j < stacks.size(); ++j) { if (API.instance().getComparer().isEqual(stack, stacks.get(j), IComparer.COMPARE_NBT)) { amount += stacks.get(j).getAmount(); combinedIndices.add(j); } } if (displayMb) { data = Component.literal(API.instance().getQuantityFormatter().formatInBucketForm(amount) + " ").append(data); } tooltip.add(data.setStyle(Styles.GRAY)); } } } // @Volatile: From Screen#getTooltipFromItem public static List getTooltipFromItem(ItemStack stack) { Minecraft minecraft = Minecraft.getInstance(); return stack.getTooltipLines(minecraft.player, minecraft.options.advancedItemTooltips ? TooltipFlag.Default.ADVANCED : TooltipFlag.Default.NORMAL); } public static boolean inBounds(int x, int y, int w, int h, double ox, double oy) { return ox >= x && ox <= x + w && oy >= y && oy <= y + h; } public static TextureAtlasSprite getSprite(BakedModel coverModel, BlockState coverState, Direction facing, RandomSource rand) { TextureAtlasSprite sprite = null; try { for (RenderType layer : coverModel.getRenderTypes(coverState, rand, ModelData.EMPTY)) { for (BakedQuad bakedQuad : coverModel.getQuads(coverState, facing, rand, ModelData.EMPTY, layer)) { return bakedQuad.getSprite(); } for (BakedQuad bakedQuad : coverModel.getQuads(coverState, null, rand)) { if (sprite == null) { sprite = bakedQuad.getSprite(); } if (bakedQuad.getDirection() == facing) { return bakedQuad.getSprite(); } } } } catch (Exception e) { // NO OP } if (sprite == null) { try { sprite = coverModel.getParticleIcon(); } catch (Exception e) { // NO OP } } if (sprite == null) { for (BakedQuad quad : Minecraft.getInstance().getModelManager().getMissingModel().getQuads(coverState, facing, rand)) { return quad.getSprite(); } } return sprite; } public static ItemTransforms getDefaultBlockTransforms() { var thirdperson = getTransform(0, 2.5f, 0, 75, 45, 0, 0.375f); return new ItemTransforms( thirdperson, thirdperson, getTransform(0, 0, 0, 0, 225, 0, 0.4f), getTransform(0, 0, 0, 0, 45, 0, 0.4f), ItemTransform.NO_TRANSFORM, getTransform(-3, 1, 0, 30, 225, 0, 0.625f), getTransform(0, 3, 0, 0, 0, 0, 0.25f), getTransform(0, 0, 0, 0, 0, 0, 0.5f), ImmutableMap.of()); } private static ItemTransform getTransform(float tx, float ty, float tz, float ax, float ay, float az, float s) { return new ItemTransform( new Vector3f(ax, ay, az), new Vector3f(tx / 16, ty / 16, tz / 16), new Vector3f(s, s, s) ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/StackUtils.java ================================================ package com.refinedmods.refinedstorage.util; import com.refinedmods.refinedstorage.api.storage.StorageType; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDisk; import com.refinedmods.refinedstorage.api.storage.disk.IStorageDiskProvider; import com.refinedmods.refinedstorage.api.storage.tracker.StorageTrackerEntry; import com.refinedmods.refinedstorage.apiimpl.API; import com.refinedmods.refinedstorage.inventory.item.BaseItemHandler; import com.refinedmods.refinedstorage.network.grid.GridStackDelta; import com.refinedmods.refinedstorage.screen.grid.stack.FluidGridStack; import com.refinedmods.refinedstorage.screen.grid.stack.ItemGridStack; import java.util.UUID; import java.util.function.Function; import javax.annotation.Nonnull; import javax.annotation.Nullable; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.neoforged.neoforge.attachment.AttachmentInternals; import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.fluids.FluidStack; import net.neoforged.neoforge.fluids.FluidType; import net.neoforged.neoforge.fluids.capability.IFluidHandler; import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; import net.neoforged.neoforge.items.IItemHandler; import net.neoforged.neoforge.items.IItemHandlerModifiable; import net.neoforged.neoforge.items.ItemHandlerHelper; import org.apache.commons.lang3.tuple.Pair; public final class StackUtils { public static final ItemStack EMPTY_BUCKET = new ItemStack(Items.BUCKET); private static final String NBT_INVENTORY = "Inventory_%d"; private static final String NBT_SLOT = "Slot"; private static final String NBT_ITEM_ID = "Id"; private static final String NBT_ITEM_QUANTITY = "Quantity"; private static final String NBT_ITEM_NBT = "NBT"; private StackUtils() { } // @Volatile: from FriendlyByteBuf#writeItem, but allows int item stack counts. public static void writeItemStack(FriendlyByteBuf buf, @Nonnull ItemStack stack) { if (stack.isEmpty()) { buf.writeBoolean(false); } else { buf.writeBoolean(true); Item item = stack.getItem(); buf.writeId(BuiltInRegistries.ITEM, item); buf.writeInt(stack.getCount()); CompoundTag compoundtag = null; if (item.isDamageable(stack) || item.shouldOverrideMultiplayerNbt()) { compoundtag = stack.getTag(); } compoundtag = AttachmentInternals.addAttachmentsToTag(compoundtag, stack, false); buf.writeNbt(compoundtag); } } // @Volatile: from FriendlyByteBuf#readItem, but allows int item stack counts. public static ItemStack readItemStack(FriendlyByteBuf buf) { if (!buf.readBoolean()) { return ItemStack.EMPTY; } else { Item item = buf.readById(BuiltInRegistries.ITEM); int i = buf.readInt(); return AttachmentInternals.reconstructItemStack(item, i, buf.readNbt()); } } public static void writeItemGridStackDelta(FriendlyByteBuf buf, GridStackDelta delta) { buf.writeInt(delta.change()); writeItemGridStack(buf, delta.stack()); } public static void writeItemGridStack(FriendlyByteBuf buf, ItemGridStack stack) { writeItemStack(buf, stack.getStack()); buf.writeBoolean(stack.isCraftable()); buf.writeUUID(stack.getId()); buf.writeBoolean(stack.getOtherId() != null); if (stack.getOtherId() != null) { buf.writeUUID(stack.getOtherId()); } if (stack.getTrackerEntry() == null) { buf.writeBoolean(false); } else { buf.writeBoolean(true); buf.writeLong(stack.getTrackerEntry().getTime()); buf.writeUtf(stack.getTrackerEntry().getName()); } } public static GridStackDelta readItemGridStackDelta(FriendlyByteBuf buf) { int delta = buf.readInt(); return new GridStackDelta<>(delta, readItemGridStack(buf)); } public static ItemGridStack readItemGridStack(FriendlyByteBuf buf) { ItemStack stack = readItemStack(buf); boolean craftable = buf.readBoolean(); UUID id = buf.readUUID(); UUID otherId = null; if (buf.readBoolean()) { otherId = buf.readUUID(); } StorageTrackerEntry entry = null; if (buf.readBoolean()) { entry = new StorageTrackerEntry(buf.readLong(), PacketBufferUtils.readString(buf)); } return new ItemGridStack(id, otherId, stack, craftable, entry); } public static void writeFluidGridStackDelta(FriendlyByteBuf buf, GridStackDelta delta) { buf.writeInt(delta.change()); writeFluidGridStack(buf, delta.stack()); } public static void writeFluidGridStack(FriendlyByteBuf buf, FluidGridStack stack) { stack.getStack().writeToPacket(buf); buf.writeBoolean(stack.isCraftable()); buf.writeUUID(stack.getId()); buf.writeBoolean(stack.getOtherId() != null); if (stack.getOtherId() != null) { buf.writeUUID(stack.getOtherId()); } if (stack.getTrackerEntry() == null) { buf.writeBoolean(false); } else { buf.writeBoolean(true); buf.writeLong(stack.getTrackerEntry().getTime()); buf.writeUtf(stack.getTrackerEntry().getName()); } } public static GridStackDelta readFluidGridStackDelta(FriendlyByteBuf buf) { int delta = buf.readInt(); return new GridStackDelta<>(delta, readFluidGridStack(buf)); } public static FluidGridStack readFluidGridStack(FriendlyByteBuf buf) { FluidStack stack = FluidStack.readFromPacket(buf); boolean craftable = buf.readBoolean(); UUID id = buf.readUUID(); UUID otherId = null; if (buf.readBoolean()) { otherId = buf.readUUID(); } StorageTrackerEntry entry = null; if (buf.readBoolean()) { entry = new StorageTrackerEntry(buf.readLong(), PacketBufferUtils.readString(buf)); } return new FluidGridStack(id, otherId, stack, craftable, entry); } @SuppressWarnings("unchecked") public static void createStorages(ServerLevel level, ItemStack diskStack, int slot, IStorageDisk[] itemDisks, IStorageDisk[] fluidDisks, Function, IStorageDisk> itemDiskWrapper, Function, IStorageDisk> fluidDiskWrapper) { if (diskStack.isEmpty()) { itemDisks[slot] = null; fluidDisks[slot] = null; } else { IStorageDisk disk = API.instance().getStorageDiskManager(level).getByStack(diskStack); if (disk != null) { StorageType type = ((IStorageDiskProvider) diskStack.getItem()).getType(); if (type == StorageType.ITEM) { itemDisks[slot] = itemDiskWrapper.apply(disk); } else if (type == StorageType.FLUID) { fluidDisks[slot] = fluidDiskWrapper.apply(disk); } } else { itemDisks[slot] = null; fluidDisks[slot] = null; } } } public static void writeItems(IItemHandler handler, int id, CompoundTag tag, Function serializer) { ListTag tagList = new ListTag(); for (int i = 0; i < handler.getSlots(); i++) { if (!handler.getStackInSlot(i).isEmpty()) { CompoundTag stackTag = serializer.apply(handler.getStackInSlot(i)); stackTag.putInt(NBT_SLOT, i); tagList.add(stackTag); } } tag.put(String.format(NBT_INVENTORY, id), tagList); } public static void writeItems(IItemHandler handler, int id, CompoundTag tag) { writeItems(handler, id, tag, stack -> stack.save(new CompoundTag())); } public static void readItems(IItemHandlerModifiable handler, int id, CompoundTag tag, Function deserializer) { String name = String.format(NBT_INVENTORY, id); if (tag.contains(name)) { ListTag tagList = tag.getList(name, Tag.TAG_COMPOUND); for (int i = 0; i < tagList.size(); i++) { int slot = tagList.getCompound(i).getInt(NBT_SLOT); if (slot >= 0 && slot < handler.getSlots()) { handler.setStackInSlot(slot, deserializer.apply(tagList.getCompound(i))); } } } } public static void readItems(IItemHandlerModifiable handler, int id, CompoundTag tag) { readItems(handler, id, tag, ItemStack::of); } public static void readItems(BaseItemHandler handler, int id, CompoundTag tag) { handler.setReading(true); readItems(handler, id, tag, ItemStack::of); handler.setReading(false); } public static void writeItems(Container inventory, int id, CompoundTag tag) { ListTag tagList = new ListTag(); for (int i = 0; i < inventory.getContainerSize(); i++) { if (!inventory.getItem(i).isEmpty()) { CompoundTag stackTag = new CompoundTag(); stackTag.putInt(NBT_SLOT, i); inventory.getItem(i).save(stackTag); tagList.add(stackTag); } } tag.put(String.format(NBT_INVENTORY, id), tagList); } public static void readItems(Container inventory, int id, CompoundTag tag) { String name = String.format(NBT_INVENTORY, id); if (tag.contains(name)) { ListTag tagList = tag.getList(name, Tag.TAG_COMPOUND); for (int i = 0; i < tagList.size(); i++) { int slot = tagList.getCompound(i).getInt(NBT_SLOT); ItemStack stack = ItemStack.of(tagList.getCompound(i)); if (!stack.isEmpty()) { inventory.setItem(slot, stack); } } } } public static FluidStack copy(FluidStack stack, int size) { FluidStack copy = stack.copy(); copy.setAmount(size); return copy; } public static FluidStack copy(@Nullable FluidStack stack) { return stack == null ? null : stack.copy(); } public static Pair getFluid(ItemStack stack, boolean simulate) { if (stack.isEmpty()) { return Pair.of(ItemStack.EMPTY, FluidStack.EMPTY); } if (stack.getCount() > 1) { stack = ItemHandlerHelper.copyStackWithSize(stack, 1); } IFluidHandlerItem handler = stack.getCapability(Capabilities.FluidHandler.ITEM); if (handler != null) { FluidStack result = handler.drain(FluidType.BUCKET_VOLUME, simulate ? IFluidHandler.FluidAction.SIMULATE : IFluidHandler.FluidAction.EXECUTE); return Pair.of(handler.getContainer(), result); } return Pair.of(ItemStack.EMPTY, FluidStack.EMPTY); } public static CompoundTag serializeStackToNbt(@Nonnull ItemStack stack) { CompoundTag itemTag = new CompoundTag(); ResourceLocation key = BuiltInRegistries.ITEM.getKey(stack.getItem()); itemTag.putString(NBT_ITEM_ID, key.toString()); itemTag.putInt(NBT_ITEM_QUANTITY, stack.getCount()); var tag = AttachmentInternals.addAttachmentsToTag(stack.getTag(), stack, true); if (tag != null) { itemTag.put(NBT_ITEM_NBT, tag); } return itemTag; } @Nonnull public static ItemStack deserializeStackFromNbt(CompoundTag tag) { return AttachmentInternals.reconstructItemStack( BuiltInRegistries.ITEM.get(new ResourceLocation(tag.getString(NBT_ITEM_ID))), tag.getInt(NBT_ITEM_QUANTITY), tag.contains(NBT_ITEM_NBT) ? tag.getCompound(NBT_ITEM_NBT) : null ); } } ================================================ FILE: src/main/java/com/refinedmods/refinedstorage/util/TimeUtils.java ================================================ package com.refinedmods.refinedstorage.util; import net.minecraft.client.resources.language.I18n; public final class TimeUtils { private static final long SECOND = 1000; private static final long MINUTE = SECOND * 60; private static final long HOUR = MINUTE * 60; private static final long DAY = HOUR * 24; private static final long WEEK = DAY * 7; private static final long YEAR = DAY * 365; private TimeUtils() { } public static String getAgo(long ago, String by) { long diff = System.currentTimeMillis() - ago; if (diff < SECOND * 10) { return I18n.get("misc.refinedstorage.last_modified.just_now", by); } else if (diff < MINUTE) { return I18n.get("misc.refinedstorage.last_modified.second" + ((diff / SECOND) > 1 ? "s" : ""), diff / SECOND, by); } else if (diff < HOUR) { return I18n.get("misc.refinedstorage.last_modified.minute" + ((diff / MINUTE) > 1 ? "s" : ""), diff / MINUTE, by); } else if (diff < DAY) { return I18n.get("misc.refinedstorage.last_modified.hour" + ((diff / HOUR) > 1 ? "s" : ""), diff / HOUR, by); } else if (diff < WEEK) { return I18n.get("misc.refinedstorage.last_modified.day" + ((diff / DAY) > 1 ? "s" : ""), diff / DAY, by); } else if (diff < YEAR) { return I18n.get("misc.refinedstorage.last_modified.week" + ((diff / WEEK) > 1 ? "s" : ""), diff / WEEK, by); } return I18n.get("misc.refinedstorage.last_modified.year" + ((diff / YEAR) > 1 ? "s" : ""), diff / YEAR, by); } } ================================================ FILE: src/main/resources/META-INF/accesstransformer.cfg ================================================ protected net.minecraft.world.inventory.AbstractContainerMenu lastSlots protected net.minecraft.world.inventory.AbstractContainerMenu containerListeners protected net.minecraft.client.gui.components.EditBox canLoseFocus public net.minecraft.client.gui.components.Checkbox selected public-f net.minecraft.world.inventory.Slot y public net.minecraft.client.gui.GuiGraphics renderTooltipInternal(Lnet/minecraft/client/gui/Font;Ljava/util/List;IILnet/minecraft/client/gui/screens/inventory/tooltip/ClientTooltipPositioner;)V ================================================ FILE: src/main/resources/META-INF/mods.toml ================================================ modLoader = "javafml" loaderVersion = "[2,)" issueTrackerURL = "https://github.com/refinedmods/refinedstorage" license="MIT" [[mods]] modId = "refinedstorage" version = "${version}" displayName = "Refined Storage" displayURL = "https://refinedmods.com/refined-storage" logoFile = "logo.png" authors = "Refined Mods" description = ''' An elegant solution to your hoarding problem ''' ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/1024k_fluid_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/1024k_fluid_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/16k_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/16k_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/1k_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/1k_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/256k_fluid_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/256k_fluid_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/4096k_fluid_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/4096k_fluid_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/4k_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/4k_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/64k_fluid_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/64k_fluid_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/64k_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/64k_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/cable.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/constructor.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } }, { "when": { "direction": "north", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected" } }, { "when": { "direction": "east", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected", "y": 90 } }, { "when": { "direction": "south", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected", "x": 180 } }, { "when": { "direction": "west", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected", "y": 270 } }, { "when": { "direction": "up", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected", "x": 270 } }, { "when": { "direction": "down", "connected": true }, "apply": { "model": "refinedstorage:block/constructor_connected", "x": 90 } }, { "when": { "direction": "north", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected" } }, { "when": { "direction": "east", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected", "y": 90 } }, { "when": { "direction": "south", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected", "x": 180 } }, { "when": { "direction": "west", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected", "y": 270 } }, { "when": { "direction": "up", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected", "x": 270 } }, { "when": { "direction": "down", "connected": false }, "apply": { "model": "refinedstorage:block/constructor_disconnected", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/creative_fluid_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/creative_fluid_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/creative_portable_grid.json ================================================ { "variants": { "": { "model": "refinedstorage:block/portable_grid" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/creative_storage_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/creative_storage_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/destructor.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } }, { "when": { "direction": "north", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected" } }, { "when": { "direction": "east", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected", "y": 90 } }, { "when": { "direction": "south", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected", "x": 180 } }, { "when": { "direction": "west", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected", "y": 270 } }, { "when": { "direction": "up", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected", "x": 270 } }, { "when": { "direction": "down", "connected": true }, "apply": { "model": "refinedstorage:block/destructor_connected", "x": 90 } }, { "when": { "direction": "north", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected" } }, { "when": { "direction": "east", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected", "y": 90 } }, { "when": { "direction": "south", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected", "x": 180 } }, { "when": { "direction": "west", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected", "y": 270 } }, { "when": { "direction": "up", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected", "x": 270 } }, { "when": { "direction": "down", "connected": false }, "apply": { "model": "refinedstorage:block/destructor_disconnected", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/disk_drive.json ================================================ { "variants": { "": { "model": "refinedstorage:block/disk_drive" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/exporter.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } }, { "when": { "direction": "north" }, "apply": { "model": "refinedstorage:block/exporter" } }, { "when": { "direction": "east" }, "apply": { "model": "refinedstorage:block/exporter", "y": 90 } }, { "when": { "direction": "south" }, "apply": { "model": "refinedstorage:block/exporter", "x": 180 } }, { "when": { "direction": "west" }, "apply": { "model": "refinedstorage:block/exporter", "y": 270 } }, { "when": { "direction": "up" }, "apply": { "model": "refinedstorage:block/exporter", "x": 270 } }, { "when": { "direction": "down" }, "apply": { "model": "refinedstorage:block/exporter", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/external_storage.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } }, { "when": { "direction": "north" }, "apply": { "model": "refinedstorage:block/external_storage" } }, { "when": { "direction": "east" }, "apply": { "model": "refinedstorage:block/external_storage", "y": 90 } }, { "when": { "direction": "south" }, "apply": { "model": "refinedstorage:block/external_storage", "x": 180 } }, { "when": { "direction": "west" }, "apply": { "model": "refinedstorage:block/external_storage", "y": 270 } }, { "when": { "direction": "up" }, "apply": { "model": "refinedstorage:block/external_storage", "x": 270 } }, { "when": { "direction": "down" }, "apply": { "model": "refinedstorage:block/external_storage", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/fluid_interface.json ================================================ { "variants": { "connected=true": { "model": "refinedstorage:block/fluid_interface_connected" }, "connected=false": { "model": "refinedstorage:block/fluid_interface_disconnected" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/importer.json ================================================ { "multipart": [ { "apply": { "model": "refinedstorage:block/cable_core" } }, { "when": { "north": true }, "apply": { "model": "refinedstorage:block/cable_extension" } }, { "when": { "east": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 90 } }, { "when": { "south": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 180 } }, { "when": { "west": true }, "apply": { "model": "refinedstorage:block/cable_extension", "y": 270 } }, { "when": { "up": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 270 } }, { "when": { "down": true }, "apply": { "model": "refinedstorage:block/cable_extension", "x": 90 } }, { "when": { "direction": "north" }, "apply": { "model": "refinedstorage:block/importer" } }, { "when": { "direction": "east" }, "apply": { "model": "refinedstorage:block/importer", "y": 90 } }, { "when": { "direction": "south" }, "apply": { "model": "refinedstorage:block/importer", "x": 180 } }, { "when": { "direction": "west" }, "apply": { "model": "refinedstorage:block/importer", "y": 270 } }, { "when": { "direction": "up" }, "apply": { "model": "refinedstorage:block/importer", "x": 270 } }, { "when": { "direction": "down" }, "apply": { "model": "refinedstorage:block/importer", "x": 90 } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/interface.json ================================================ { "variants": { "connected=true": { "model": "refinedstorage:block/interface_connected" }, "connected=false": { "model": "refinedstorage:block/interface_disconnected" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/machine_casing.json ================================================ { "variants": { "": { "model": "refinedstorage:block/machine_casing" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/portable_grid.json ================================================ { "variants": { "": { "model": "refinedstorage:block/portable_grid" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/quartz_enriched_iron_block.json ================================================ { "variants": { "": { "model": "refinedstorage:block/quartz_enriched_iron_block" } } } ================================================ FILE: src/main/resources/assets/refinedstorage/blockstates/storage_monitor.json ================================================ { "variants": { "direction=north": { "model": "refinedstorage:block/storage_monitor", "y": 0 }, "direction=east": { "model": "refinedstorage:block/storage_monitor", "y": 90 }, "direction=south": { "model": "refinedstorage:block/storage_monitor", "y": 180 }, "direction=west": { "model": "refinedstorage:block/storage_monitor", "y": 270 } } } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/de_de.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage Fassaden", "key.refinedstorage.focusSearchBar": "Konsolensuchleiste Selektieren", "key.refinedstorage.clearGridCraftingMatrix": "Werkbank in der Konsole leeren", "gui.refinedstorage.controller": "Kontrollblock", "gui.refinedstorage.creative_controller": "Kreativ-Kontrollblock", "gui.refinedstorage.grid": "Konsole", "gui.refinedstorage.grid.craft": "Herstellen", "gui.refinedstorage.crafting_grid": "Fertigungskonsole", "gui.refinedstorage.pattern_grid": "Vorlagenkonsole", "gui.refinedstorage.grid.pattern_create": "Vorlage herstellen", "gui.refinedstorage.fluid_grid": "Flüssigkeitskonsole", "gui.refinedstorage.portable_grid": "Mobile Konsole", "gui.refinedstorage.item_amount": "Menge an Items", "gui.refinedstorage.fluid_amount": "Flüssigkeitsmenge in mB", "gui.refinedstorage.disk_drive": "Laufwerk", "gui.refinedstorage.disk_drive.disks": "Speicherplatten", "gui.refinedstorage.external_storage": "Externer Speicher", "gui.refinedstorage.importer": "Importierer", "gui.refinedstorage.exporter": "Exportierer", "gui.refinedstorage.detector": "Detektor", "gui.refinedstorage.destructor": "Destruktor", "gui.refinedstorage.constructor": "Konstruktor", "gui.refinedstorage.relay": "Relais", "gui.refinedstorage.interface.import": "Importschnittstelle", "gui.refinedstorage.interface.export": "Exportschnittstelle", "gui.refinedstorage.crafting_monitor": "Fertigungsmonitor", "gui.refinedstorage.wireless_crafting_monitor": "Mobile Fertigungskonsole", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d angefragt", "gui.refinedstorage.crafting_monitor.stored": "Gespeichert: %d", "gui.refinedstorage.crafting_monitor.missing": "Fehlt", "gui.refinedstorage.crafting_monitor.processing": "Verarbeitung", "gui.refinedstorage.crafting_monitor.scheduled": "Geplant: %d", "gui.refinedstorage.crafting_monitor.crafting": "Fertigung: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "Maschine akzeptiert Item nicht", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "Maschine akzeptiert Flüssigkeit nicht", "gui.refinedstorage.crafting_monitor.machine_none": "Keine Maschine gefunden", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Fertiger ist gesperrt", "gui.refinedstorage.wireless_transmitter": "Funksender", "gui.refinedstorage.wireless_transmitter.distance": "%d Blöcke", "gui.refinedstorage.crafter": "Fertigungseinheit", "gui.refinedstorage.filter": "Filter", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Mod Filter", "gui.refinedstorage.network_transmitter": "Netzwerksender", "gui.refinedstorage.network_transmitter.distance": "%d Blöcke", "gui.refinedstorage.network_transmitter.missing_card": "Fehlende Netzwerk Karte", "gui.refinedstorage.fluid_interface": "Flüssigkeitsschnittstelle", "gui.refinedstorage.fluid_interface.in": "Ein", "gui.refinedstorage.fluid_interface.out": "Aus", "gui.refinedstorage.crafting_preview": "Fertigungsvorschau", "gui.refinedstorage.crafting_preview.to_craft": "Herzustellen: %d", "gui.refinedstorage.crafting_preview.available": "Verfügbar: %d", "gui.refinedstorage.crafting_preview.missing": "Fehlt: %d", "gui.refinedstorage.crafting_preview.error": "Anfrage fehlgeschlagen", "gui.refinedstorage.crafting_preview.error.recursive.0": "Eine benötigte Resource braucht", "gui.refinedstorage.crafting_preview.error.recursive.1": "sich selbst.", "gui.refinedstorage.crafting_preview.error.recursive.2": "Entferne diese Vorlage um sicherzugehen", "gui.refinedstorage.crafting_preview.error.recursive.3": "dass sie nicht zur Herstellung verwendet wird.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Fehlerhafte Vorlage:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "Die Berechnung der Fertigung war zu komplex", "gui.refinedstorage.crafting_preview.error.too_complex.1": "und wurde angehalten um Serverleistung zu sparen.", "gui.refinedstorage.security_manager": "Sicherheitsmanager", "gui.refinedstorage.security_manager.configure": "Konfiguriere", "gui.refinedstorage.security_manager.permission.0": "Einfügen", "gui.refinedstorage.security_manager.permission.0.tooltip": "Items in das Netzwerk einfügen", "gui.refinedstorage.security_manager.permission.1": "Extrahieren", "gui.refinedstorage.security_manager.permission.1.tooltip": "Items aus dem Netz herausholen", "gui.refinedstorage.security_manager.permission.2": "Automatisches Herstellen", "gui.refinedstorage.security_manager.permission.2.tooltip": "Fertigungsprozesse starten, abbrechen und überwachen", "gui.refinedstorage.security_manager.permission.3": "Modifizieren", "gui.refinedstorage.security_manager.permission.3.tooltip": "Auf Block GUIs zugreifen", "gui.refinedstorage.security_manager.permission.4": "Bauen", "gui.refinedstorage.security_manager.permission.4.tooltip": "Geräte zum Netzwerk hinzufügen oder entfernen", "gui.refinedstorage.security_manager.permission.5": "Sicherheit", "gui.refinedstorage.security_manager.permission.5.tooltip": "Sicherheitseinstellungen ändern", "gui.refinedstorage.storage_monitor": "Lagermonitor", "gui.refinedstorage.crafter_manager": "Vorlagenmanager", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Verbrauch: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Belegt: %s", "misc.refinedstorage.storage.stored_capacity": "Belegt: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% belegt", "misc.refinedstorage.network_item.tooltip": "Verbungen mit %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Kein Funksender in Reichweite", "misc.refinedstorage.network_item.not_found": "Kontrollblock nicht gefunden.", "misc.refinedstorage.network_card.tooltip": "Verbunden mit %d, %d, %d in %s.", "misc.refinedstorage.pattern.inputs": "Ausgangsmaterialien", "misc.refinedstorage.pattern.outputs": "Ergebnis", "misc.refinedstorage.pattern.invalid": "Ungültige Vorlage", "misc.refinedstorage.security.no_permission": "Du hast keine Berechtigung dafür.", "misc.refinedstorage.start": "Start", "misc.refinedstorage.clear": "Löschen", "misc.refinedstorage.set": "Setzen", "misc.refinedstorage.cancel_all": "Alles Anhalten", "misc.refinedstorage.priority": "Priorität", "misc.refinedstorage.processing": "Verarbeitung", "misc.refinedstorage.total": "%s insgesamt", "misc.refinedstorage.last_modified.just_now": "Zuletzt geändert: Gerade eben von %s", "misc.refinedstorage.last_modified.second": "Zuletzt geändert: Vor %d Sekunde von %s", "misc.refinedstorage.last_modified.seconds": "Zuletzt geändert: Vor %d Sekunden von %s", "misc.refinedstorage.last_modified.minute": "Zuletzt geändert: Vor %d Minute von %s", "misc.refinedstorage.last_modified.minutes": "Zuletzt geändert: Vor %d Minuten von %s", "misc.refinedstorage.last_modified.hour": "Zuletzt geändert: Vor %d Stunde von %s", "misc.refinedstorage.last_modified.hours": "Zuletzt geändert: Vor %d Stunden von %s", "misc.refinedstorage.last_modified.day": "Zuletzt geändert: Vor %d Tag von %s", "misc.refinedstorage.last_modified.days": "Zuletzt geändert: Vor %d Tagen von %s", "misc.refinedstorage.last_modified.week": "Zuletzt geändert: Vor %d Woche von %s", "misc.refinedstorage.last_modified.weeks": "Zuletzt geändert: Vor %d Wochen von %s", "misc.refinedstorage.last_modified.year": "Zuletzt geändert: Vor %d Jahr von %s", "misc.refinedstorage.last_modified.years": "Zuletzt geändert: Vor %d Jahren von %s", "sidebutton.refinedstorage.redstone_mode": "Redstone Modus", "sidebutton.refinedstorage.redstone_mode.0": "Ignoriere Redstone Signal", "sidebutton.refinedstorage.redstone_mode.1": "Nur mit Redstone Signal", "sidebutton.refinedstorage.redstone_mode.2": "Nur ohne Redstone Signal", "sidebutton.refinedstorage.crafter_mode": "Redstone Modus", "sidebutton.refinedstorage.crafter_mode.0": "Ignoriere Redstone Signal", "sidebutton.refinedstorage.crafter_mode.1": "Redstone Signal schaltet Autofertigung frei", "sidebutton.refinedstorage.crafter_mode.2": "Redstone Signal sperrt Autofertigung", "sidebutton.refinedstorage.crafter_mode.3": "Redstone Impuls fügt nächstes Rezept ein", "sidebutton.refinedstorage.grid.view_type": "Anzeige", "sidebutton.refinedstorage.grid.view_type.0": "Normal", "sidebutton.refinedstorage.grid.view_type.1": "Keine Vorlagen", "sidebutton.refinedstorage.grid.view_type.2": "Nur Vorlagen", "sidebutton.refinedstorage.grid.sorting.direction": "Sortierung", "sidebutton.refinedstorage.grid.sorting.direction.0": "Aufsteigend", "sidebutton.refinedstorage.grid.sorting.direction.1": "Absteigend", "sidebutton.refinedstorage.grid.sorting.type": "Sortieren Nach", "sidebutton.refinedstorage.grid.sorting.type.0": "Menge", "sidebutton.refinedstorage.grid.sorting.type.1": "Name", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Zuletzt Geändert", "sidebutton.refinedstorage.grid.search_box_mode": "Suchleistenmodus", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normal (Autoselektiert)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI synchronisiert", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI synchronisiert (Autoselektiert)", "sidebutton.refinedstorage.grid.size": "Größe", "sidebutton.refinedstorage.grid.size.0": "Auto", "sidebutton.refinedstorage.grid.size.1": "Klein", "sidebutton.refinedstorage.grid.size.2": "Mittel", "sidebutton.refinedstorage.grid.size.3": "Groß", "sidebutton.refinedstorage.mode": "Modus", "sidebutton.refinedstorage.mode.whitelist": "Whitelist", "sidebutton.refinedstorage.mode.blacklist": "Blacklist", "sidebutton.refinedstorage.iomode": "IO Modus", "sidebutton.refinedstorage.iomode.insert": "In Netzwerk importieren", "sidebutton.refinedstorage.iomode.extract": "Aus Netzwerk exportieren", "sidebutton.refinedstorage.type": "Typ", "sidebutton.refinedstorage.type.0": "Items", "sidebutton.refinedstorage.type.1": "Flüssigkeiten", "sidebutton.refinedstorage.detector.mode": "Modus", "sidebutton.refinedstorage.detector.mode.0": "Signal Wenn Weniger", "sidebutton.refinedstorage.detector.mode.1": "Signal Wenn Gleich", "sidebutton.refinedstorage.detector.mode.2": "Signal Wenn Mehr", "sidebutton.refinedstorage.constructor.drop": "Blöcke fallen lassen anstatt zu platzieren", "sidebutton.refinedstorage.destructor.pickup": "Items einsammeln anstatt abzubauen", "sidebutton.refinedstorage.access_type": "Zugriffsmodus", "sidebutton.refinedstorage.access_type.0": "Importieren und Exportieren", "sidebutton.refinedstorage.access_type.1": "Nur Importieren", "sidebutton.refinedstorage.access_type.2": "Nur Exportieren", "block.refinedstorage.controller": "Kontrollblock", "block.refinedstorage.controller.creative_controller": "Kreativ-Kontrollblock", "block.refinedstorage.cable": "Kabel", "block.refinedstorage.grid": "Konsole", "block.refinedstorage.crafting_grid": "Fertigungskonsole", "block.refinedstorage.pattern_grid": "Vorlagenkonsole", "block.refinedstorage.fluid_grid": "Flüssigkeitskonsole", "block.refinedstorage.disk_drive": "Laufwerk", "block.refinedstorage.disk_manipulator": "Speichermanipulator", "block.refinedstorage.external_storage": "Externer Speicher", "block.refinedstorage.importer": "Importierer", "block.refinedstorage.exporter": "Exportierer", "block.refinedstorage.detector": "Detektor", "block.refinedstorage.machine_casing": "Gehäuse", "block.refinedstorage.destructor": "Destruktor", "block.refinedstorage.constructor": "Konstruktor", "block.refinedstorage.1k_storage_block": "1k Speicherblock", "block.refinedstorage.4k_storage_block": "4k Speicherblock", "block.refinedstorage.16k_storage_block": "16k Speicherblock", "block.refinedstorage.64k_storage_block": "64k Speicherblock", "block.refinedstorage.creative_storage_block": "Kreativ-Speicherblock", "block.refinedstorage.relay": "Relais", "block.refinedstorage.interface": "Schnittstelle", "block.refinedstorage.crafting_monitor": "Fertigungsmonitor", "block.refinedstorage.wireless_transmitter": "Funksender", "block.refinedstorage.wireless_transmitter.tooltip": "Muss an %s platziert werden.", "block.refinedstorage.crafter": "Fertiger", "block.refinedstorage.network_receiver": "Netzwerkempfänger", "block.refinedstorage.network_transmitter": "Netzwerksender", "block.refinedstorage.fluid_interface": "Flüssigkeitsschnittstelle", "block.refinedstorage.64k_fluid_storage_block": "64k Flüssigspeicherblock", "block.refinedstorage.256k_fluid_storage_block": "256k Flüssigspeicherblock", "block.refinedstorage.1024k_fluid_storage_block": "1024k Flüssigspeicherblock", "block.refinedstorage.4096k_fluid_storage_block": "4096k Flüssigspeicherblock", "block.refinedstorage.creative_fluid_storage_block": "Kreativ-Flüssigspeicherblock", "block.refinedstorage.security_manager": "Sicherheitsmanager", "block.refinedstorage.quartz_enriched_iron_block": "Quarzangereicherter Eisenblock", "block.refinedstorage.storage_monitor": "Speichermonitor", "block.refinedstorage.portable_grid": "Mobile Konsole", "block.refinedstorage.creative_portable_grid": "Mobile Kreativ-Konsole", "block.refinedstorage.portable_grid.tooltip": "Schleiche um das in der Welt zu platzieren", "block.refinedstorage.crafter_manager": "Fertigungsmanager", "item.refinedstorage.1k_storage_disk": "1k Speicherzelle", "item.refinedstorage.4k_storage_disk": "4k Speicherzelle", "item.refinedstorage.16k_storage_disk": "16k Speicherzelle", "item.refinedstorage.64k_storage_disk": "64k Speicherzelle", "item.refinedstorage.creative_storage_disk": "Kreativ-Speicherzelle", "item.refinedstorage.64k_fluid_storage_disk": "64k Flüssigspeicherzelle", "item.refinedstorage.256k_fluid_storage_disk": "256k Flüssigspeicherzelle", "item.refinedstorage.1024k_fluid_storage_disk": "1024k Flüssigspeicherzelle", "item.refinedstorage.4096k_fluid_storage_disk": "4096k Flüssigspeicherzelle", "item.refinedstorage.creative_fluid_storage_disk": "Kreativ-Flüssigspeicherzelle", "item.refinedstorage.wireless_grid": "Mobile Konsole", "item.refinedstorage.creative_wireless_grid": "Mobile Kreativkonsole", "item.refinedstorage.wireless_fluid_grid": "Mobile Flüssigkeitskonsole", "item.refinedstorage.creative_wireless_fluid_grid": "Mobile Kreative-Flüssigkeitskonsole", "item.refinedstorage.wireless_crafting_monitor": "Mobile Fertigungskonsole", "item.refinedstorage.creative_wireless_crafting_monitor": "Mobile Kreativ-Fertigungskonsole", "item.refinedstorage.quartz_enriched_iron": "Quarzangereichertes Eisen", "item.refinedstorage.construction_core": "Konstruktionskern", "item.refinedstorage.destruction_core": "Destruktionskern", "item.refinedstorage.silicon": "Silizium", "item.refinedstorage.raw_basic_processor": "Basisrohprozessor", "item.refinedstorage.raw_improved_processor": "Verbesserter Rohprozessor", "item.refinedstorage.raw_advanced_processor": "Fortschrittlicher Rohprozessor", "item.refinedstorage.basic_processor": "Basisprozessor", "item.refinedstorage.improved_processor": "Verbesserter Prozessor", "item.refinedstorage.advanced_processor": "Fortschrittlicher Prozessor", "item.refinedstorage.1k_storage_part": "1k Speicherkern", "item.refinedstorage.4k_storage_part": "4k Speicherkern", "item.refinedstorage.16k_storage_part": "16k Speicherkern", "item.refinedstorage.64k_storage_part": "64k Speicherkern", "item.refinedstorage.64k_fluid_storage_part": "64k Flüssigspeicherkern", "item.refinedstorage.256k_fluid_storage_part": "256k Flüssigspeicherkern", "item.refinedstorage.1024k_fluid_storage_part": "1024k Flüssigspeicherkern", "item.refinedstorage.4096k_fluid_storage_part": "4096k Flüssigspeicherkern", "item.refinedstorage.pattern": "Vorlage", "item.refinedstorage.upgrade": "Upgrade", "item.refinedstorage.range_upgrade": "Reichweitenupgrade", "item.refinedstorage.speed_upgrade": "Geschwindigkeitsupgrade", "item.refinedstorage.crafting_upgrade": "Fertigungsupgrade", "item.refinedstorage.stack_upgrade": "Stapelupgrade", "item.refinedstorage.silk_touch_upgrade": "Behutsamkeitsupgrade", "item.refinedstorage.fortune_1_upgrade": "Glücksupgrade", "item.refinedstorage.fortune_2_upgrade": "Glücksupgrade", "item.refinedstorage.fortune_3_upgrade": "Glücksupgrade", "item.refinedstorage.storage_housing": "Speichergehäuse", "item.refinedstorage.filter": "Filter", "item.refinedstorage.network_card": "Netzwerkkarte", "item.refinedstorage.wrench": "Schraubenschlüssel", "item.refinedstorage.security_card": "Sicherheitskarte", "item.refinedstorage.security_card.owner": "Besitzer: %s", "item.refinedstorage.processor_binding": "Prozessor Rohmaterial", "commands.refinedstorage.disk.create.error.disk_not_found": "Speicherzelle %s konnte nicht gefunden werden.", "commands.refinedstorage.disk.create.success": "Speicherzelle %s erfolgreich an %s gegeben.", "advancements.refinedstorage.controlling.description": "Stelle einen Kontrollblock her", "advancements.refinedstorage.connecting": "Verbinden", "advancements.refinedstorage.connecting.description": "Platziere zwei Geräte nebeneinander oder verwende ein Kabel um sie zu verbinden", "advancements.refinedstorage.conditional_connecting": "Bedingte Verbindung", "advancements.refinedstorage.conditional_connecting.description": "Stelle ein Relais her, um eine Verbindung per Redstone zu steuern", "advancements.refinedstorage.drives": "Laufwerke", "advancements.refinedstorage.drives.description": "Stelle ein Laufwerk her um Speicherzellen zu lagern", "advancements.refinedstorage.manipulating_disks": "Speichermanipulation", "advancements.refinedstorage.manipulating_disks.description": "Benutze einen Speichermanipulator, um Speicherzellen einfach zu bearbeiten", "advancements.refinedstorage.storing_items": "Items Speichern", "advancements.refinedstorage.storing_items.description": "Stelle eine Speicherzelle her und lege sie in ein Laufwerk", "advancements.refinedstorage.viewing_items": "Items Betrachten", "advancements.refinedstorage.viewing_items.description": "Stelle eine Konsole her, um mit deinem Speicher zu interagieren", "advancements.refinedstorage.portable_storage": "Tragbarer Speicher", "advancements.refinedstorage.portable_storage.description": "Stelle einen Tragbaren Speicher her, um Items außerhalb eines Netzwerks zu speichern", "advancements.refinedstorage.upgrading_your_grid": "Konsolenupgrade", "advancements.refinedstorage.upgrading_your_grid.description": "Erweitere eine Konsole zu einer Fertigungskonsole um eine Werkbank in der Konsole zu erhalten", "advancements.refinedstorage.storing_fluids": "Flüssigkeiten Speichern", "advancements.refinedstorage.storing_fluids.description": "Stelle eine Flüssigspeicherzelle her und lege sie in ein Laufwerk", "advancements.refinedstorage.viewing_fluids": "Flüssigkeiten Betrachten", "advancements.refinedstorage.viewing_fluids.description": "Stelle eine Flüssigkeitskonsole her, um mit Flüssigkeiten in deinem Speicher zu interagieren", "advancements.refinedstorage.better_than_a_barrel": "Besser als ein Fass", "advancements.refinedstorage.better_than_a_barrel.description": "Stelle einen Speichermonitor her, um mit Items in deinem Speicher abzulegen oder herauszunehmen", "advancements.refinedstorage.autocrafting": "Automatische Fertigung", "advancements.refinedstorage.autocrafting.description": "Stelle eine Fertigungseinheit her", "advancements.refinedstorage.pattern_creation": "Vorlagen", "advancements.refinedstorage.pattern_creation.description": "Stelle eine Vorlage mit einer Vorlagenkonsole her", "advancements.refinedstorage.monitoring": "Überwachung", "advancements.refinedstorage.monitoring.description": "Überprüfe den Fortschritt deiner automatischen Fertigung mit einem Fertigungsmonitor", "advancements.refinedstorage.managing_patterns": "Vorlagen Ordnen", "advancements.refinedstorage.managing_patterns.description": "Stelle einen Vorlagenmanager her, um deine Vorlagen zu sortieren", "advancements.refinedstorage.importing": "Importieren", "advancements.refinedstorage.importing.description": "Importiere Items oder Flüssigkeiten mit einem Importierer", "advancements.refinedstorage.destruction": "Zerstörung", "advancements.refinedstorage.destruction.description": "Benutze einen Destruktor, um Blöcke oder Flüssigkeiten in den Speicher zu importieren", "advancements.refinedstorage.exporting": "Exportieren", "advancements.refinedstorage.exporting.description": "Exportiere Items oder Flüssigkeiten mit einem Exportierer", "advancements.refinedstorage.construction": "Konstruktion", "advancements.refinedstorage.construction.description": "Benutze einen Konstruktor, um Blöcke oder Flüssigkeitne aus dem Speicher zu exportieren", "advancements.refinedstorage.security": "Sicherheit", "advancements.refinedstorage.security.description": "Sichere dein Netzwerk mit einem Sicherheitsmanager und einer Sicherheitskarte", "advancements.refinedstorage.wireless": "Drahtlos", "advancements.refinedstorage.wireless.description": "Übertrage ein Netzwerksignal mit einem Funksender", "advancements.refinedstorage.wireless_items": "Drahtlose Items", "advancements.refinedstorage.wireless_items.description": "Interagiere mit deinen Items über eine mobile Konsole", "advancements.refinedstorage.wireless_fluids": "Drahtlose Flüssigkeit", "advancements.refinedstorage.wireless_fluids.description": "Interagiere mit deinem Flüssigkeitsspeicher über eine mobile Flüssigkeitskonsole", "advancements.refinedstorage.wireless_monitoring": "Drahtlose Überwachung", "advancements.refinedstorage.wireless_monitoring.description": "Überprüfe drahtlos den Fertigungsfortschritt über einen mobilen Fertigungsmonitor", "advancements.refinedstorage.no_cables_required": "Kabellos", "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", "advancements.refinedstorage.upgrading": "Upgrades", "advancements.refinedstorage.upgrading.description": "Stelle ein beliebiges Upgrade her", "advancements.refinedstorage.crafting_on_demand": "Fertigung auf Befehl", "advancements.refinedstorage.crafting_on_demand.description": "Benutze ein Fertigungsupgrade in einer Schnittstelle, einem Exportierer oder einem Konstruktor um Items nach Bedarf herzustellen", "advancements.refinedstorage.detecting": "Erfassung", "advancements.refinedstorage.detecting.description": "Benutze einen Detektor um Items oder Flüssigkeiten in einem Netzwerk zu erfassen", "advancements.refinedstorage.interface_to_the_world": "Schnittstelle zur Welt", "advancements.refinedstorage.interface_to_the_world.description": "Benutze ein Interface, um gleichzeitig Items zu exportieren und zu importieren", "advancements.refinedstorage.storing_externally": "Speicher auslagern", "advancements.refinedstorage.storing_externally.description": "Benutze einen externen Speicher um externe Itemquellen wie zum Beispiel Kisten anzubinden" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/en_us.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage Covers", "key.refinedstorage.focusSearchBar": "Focus Grid Search Bar", "key.refinedstorage.clearGridCraftingMatrix": "Clear Grid Crafting Matrix", "key.refinedstorage.openWirelessGrid": "Open Wireless Grid", "key.refinedstorage.openWirelessFluidGrid": "Open Wireless Fluid Grid", "key.refinedstorage.openPortableGrid": "Open Portable Grid", "key.refinedstorage.openWirelessCraftingMonitor": "Open Wireless Crafting Monitor", "gui.refinedstorage.controller": "Controller", "gui.refinedstorage.creative_controller": "Creative Controller", "gui.refinedstorage.grid": "Grid", "gui.refinedstorage.grid.craft": "Craft", "gui.refinedstorage.crafting_grid": "Crafting Grid", "gui.refinedstorage.pattern_grid": "Pattern Grid", "gui.refinedstorage.grid.pattern_create": "Create", "gui.refinedstorage.fluid_grid": "Fluid Grid", "gui.refinedstorage.portable_grid": "Portable Grid", "gui.refinedstorage.item_amount": "Item amount", "gui.refinedstorage.fluid_amount": "Fluid amount in mB", "gui.refinedstorage.disk_drive": "Disk Drive", "gui.refinedstorage.disk_drive.disks": "Disks", "gui.refinedstorage.disk_manipulator": "Disk Manipulator", "gui.refinedstorage.disk_manipulator.in": "In", "gui.refinedstorage.disk_manipulator.out": "Out", "gui.refinedstorage.external_storage": "External Storage", "gui.refinedstorage.importer": "Importer", "gui.refinedstorage.exporter": "Exporter", "gui.refinedstorage.detector": "Detector", "gui.refinedstorage.destructor": "Destructor", "gui.refinedstorage.constructor": "Constructor", "gui.refinedstorage.relay": "Relay", "gui.refinedstorage.interface.import": "Interface Import", "gui.refinedstorage.interface.export": "Interface Export", "gui.refinedstorage.crafting_monitor": "Crafting Monitor", "gui.refinedstorage.wireless_crafting_monitor": "Wireless Crafting Monitor", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d requested", "gui.refinedstorage.crafting_monitor.stored": "Stored: %d", "gui.refinedstorage.crafting_monitor.missing": "Missing: %d", "gui.refinedstorage.crafting_monitor.processing": "Processing: %d", "gui.refinedstorage.crafting_monitor.scheduled": "Scheduled: %d", "gui.refinedstorage.crafting_monitor.crafting": "Crafting: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "Machine doesn't accept item", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "Machine doesn't accept fluid", "gui.refinedstorage.crafting_monitor.machine_none": "No machine found", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Crafter is locked", "gui.refinedstorage.wireless_transmitter": "Wireless Transmitter", "gui.refinedstorage.wireless_transmitter.distance": "%d block(s)", "gui.refinedstorage.crafter": "Crafter", "gui.refinedstorage.filter": "Filter", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Mod filter", "gui.refinedstorage.network_transmitter": "Network Transmitter", "gui.refinedstorage.network_transmitter.distance": "%d block(s)", "gui.refinedstorage.network_transmitter.missing_card": "Missing Network Card", "gui.refinedstorage.fluid_interface": "Fluid Interface", "gui.refinedstorage.fluid_interface.in": "In", "gui.refinedstorage.fluid_interface.out": "Out", "gui.refinedstorage.crafting_preview": "Crafting Preview", "gui.refinedstorage.crafting_preview.to_craft": "To craft: %d", "gui.refinedstorage.crafting_preview.available": "Available: %d", "gui.refinedstorage.crafting_preview.missing": "Missing: %d", "gui.refinedstorage.crafting_preview.error": "Request failed", "gui.refinedstorage.crafting_preview.error.recursive.0": "One of the crafting ingredients ended up needing", "gui.refinedstorage.crafting_preview.error.recursive.1": "itself.", "gui.refinedstorage.crafting_preview.error.recursive.2": "You need to remove the pattern or make sure", "gui.refinedstorage.crafting_preview.error.recursive.3": "the pattern is not used during crafting.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Offending pattern:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "The crafting task calculation was too complex", "gui.refinedstorage.crafting_preview.error.too_complex.1": "and was stopped to avoid server strain.", "gui.refinedstorage.security_manager": "Security Manager", "gui.refinedstorage.security_manager.configure": "Configure", "gui.refinedstorage.security_manager.permission.0": "Insert", "gui.refinedstorage.security_manager.permission.0.tooltip": "Inserting items or fluids to the network", "gui.refinedstorage.security_manager.permission.1": "Extract", "gui.refinedstorage.security_manager.permission.1.tooltip": "Extracting items or fluids from the network", "gui.refinedstorage.security_manager.permission.2": "Autocrafting", "gui.refinedstorage.security_manager.permission.2.tooltip": "Starting, cancelling and viewing crafting tasks", "gui.refinedstorage.security_manager.permission.3": "Modify", "gui.refinedstorage.security_manager.permission.3.tooltip": "Opening blocks", "gui.refinedstorage.security_manager.permission.4": "Build", "gui.refinedstorage.security_manager.permission.4.tooltip": "Adding or removing devices to or from the network", "gui.refinedstorage.security_manager.permission.5": "Security", "gui.refinedstorage.security_manager.permission.5.tooltip": "Ability to change security options", "gui.refinedstorage.storage_monitor": "Storage Monitor", "gui.refinedstorage.crafter_manager": "Crafter Manager", "gui.refinedstorage.alternatives": "Alternatives", "gui.refinedstorage.alternatives.apply": "Apply", "gui.refinedstorage.jei.transfer.autocrafting_available": "Autocrafting available", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRL + CLICK to request autocrafting", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMD + CLICK to request autocrafting", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Usage: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Stored: %s", "misc.refinedstorage.storage.stored_capacity": "Stored: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% full", "misc.refinedstorage.network_item.tooltip": "Linked to %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "There is no Wireless Transmitter in range.", "misc.refinedstorage.network_item.not_found": "Network not found.", "misc.refinedstorage.network_item.shortcut_not_found": "There isn't any %s in your inventory.", "misc.refinedstorage.network_item.shortcut_duplicate": "There is more than one %s in your inventory.", "misc.refinedstorage.network_item.out_of_energy": "The %s is out of energy.", "misc.refinedstorage.network_card.tooltip": "Linked to %d, %d, %d in %s.", "misc.refinedstorage.pattern.inputs": "Inputs", "misc.refinedstorage.pattern.outputs": "Outputs", "misc.refinedstorage.pattern.invalid": "Invalid pattern", "misc.refinedstorage.pattern.exact": "Uses exact mode", "misc.refinedstorage.pattern.allowed_item_tag": "Uses items from %s for %s", "misc.refinedstorage.pattern.allowed_fluid_tag": "Uses fluids from %s for %s", "misc.refinedstorage.pattern.error.processing_no_outputs": "Processing pattern has no outputs", "misc.refinedstorage.pattern.error.no_output": "Recipe has no output", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "Recipe doesn't exist", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "Tag %s is no longer applicable for %s", "misc.refinedstorage.security.no_permission": "You have no permission to perform that action.", "misc.refinedstorage.start": "Start", "misc.refinedstorage.clear": "Clear", "misc.refinedstorage.set": "Set", "misc.refinedstorage.cancel_all": "Cancel All", "misc.refinedstorage.priority": "Priority", "misc.refinedstorage.exact": "Exact", "misc.refinedstorage.processing": "Processing", "misc.refinedstorage.fluidmode": "Fluids", "misc.refinedstorage.total": "%s total", "misc.refinedstorage.last_modified.just_now": "Last modified just now by %s", "misc.refinedstorage.last_modified.second": "Last modified %d second ago by %s", "misc.refinedstorage.last_modified.seconds": "Last modified %d seconds ago by %s", "misc.refinedstorage.last_modified.minute": "Last modified %d minute ago by %s", "misc.refinedstorage.last_modified.minutes": "Last modified %d minutes ago by %s", "misc.refinedstorage.last_modified.hour": "Last modified %d hour ago by %s", "misc.refinedstorage.last_modified.hours": "Last modified %d hours ago by %s", "misc.refinedstorage.last_modified.day": "Last modified %d day ago by %s", "misc.refinedstorage.last_modified.days": "Last modified %d days ago by %s", "misc.refinedstorage.last_modified.week": "Last modified %d week ago by %s", "misc.refinedstorage.last_modified.weeks": "Last modified %d weeks ago by %s", "misc.refinedstorage.last_modified.year": "Last modified %d year ago by %s", "misc.refinedstorage.last_modified.years": "Last modified %d years ago by %s", "sidebutton.refinedstorage.exact_mode": "Exact mode", "sidebutton.refinedstorage.exact_mode.on": "On", "sidebutton.refinedstorage.exact_mode.off": "Off", "sidebutton.refinedstorage.redstone_mode": "Redstone mode", "sidebutton.refinedstorage.redstone_mode.0": "Ignore redstone signal", "sidebutton.refinedstorage.redstone_mode.1": "Only work with redstone signal", "sidebutton.refinedstorage.redstone_mode.2": "Only work without redstone signal", "sidebutton.refinedstorage.crafter_mode": "Crafter mode", "sidebutton.refinedstorage.crafter_mode.0": "Ignore redstone signal", "sidebutton.refinedstorage.crafter_mode.1": "Redstone signal unlocks autocrafting", "sidebutton.refinedstorage.crafter_mode.2": "Redstone signal locks autocrafting", "sidebutton.refinedstorage.crafter_mode.3": "Redstone pulse inserts next set", "sidebutton.refinedstorage.grid.view_type": "Display", "sidebutton.refinedstorage.grid.view_type.0": "Normal", "sidebutton.refinedstorage.grid.view_type.1": "No craftables", "sidebutton.refinedstorage.grid.view_type.2": "Only craftables", "sidebutton.refinedstorage.grid.sorting.direction": "Sorting direction", "sidebutton.refinedstorage.grid.sorting.direction.0": "Ascending", "sidebutton.refinedstorage.grid.sorting.direction.1": "Descending", "sidebutton.refinedstorage.grid.sorting.type": "Sorting type", "sidebutton.refinedstorage.grid.sorting.type.0": "Quantity", "sidebutton.refinedstorage.grid.sorting.type.1": "Name", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Last modified", "sidebutton.refinedstorage.grid.search_box_mode": "Search box mode", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normal (autoselected)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI synchronized", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI synchronized (autoselected)", "sidebutton.refinedstorage.grid.search_box_mode.4": "JEI synchronized (two-way)", "sidebutton.refinedstorage.grid.search_box_mode.5": "JEI synchronized (two-way autoselected)", "sidebutton.refinedstorage.grid.size": "Size", "sidebutton.refinedstorage.grid.size.0": "Stretch", "sidebutton.refinedstorage.grid.size.1": "Small", "sidebutton.refinedstorage.grid.size.2": "Medium", "sidebutton.refinedstorage.grid.size.3": "Large", "sidebutton.refinedstorage.mode": "Mode", "sidebutton.refinedstorage.mode.whitelist": "Whitelist", "sidebutton.refinedstorage.mode.blacklist": "Blacklist", "sidebutton.refinedstorage.iomode": "IO mode", "sidebutton.refinedstorage.iomode.insert": "Insert into network", "sidebutton.refinedstorage.iomode.extract": "Extract from network", "sidebutton.refinedstorage.type": "Type", "sidebutton.refinedstorage.type.0": "Items", "sidebutton.refinedstorage.type.1": "Fluids", "sidebutton.refinedstorage.detector.mode": "Mode", "sidebutton.refinedstorage.detector.mode.0": "Emit signal when under the amount", "sidebutton.refinedstorage.detector.mode.1": "Emit signal when on the amount", "sidebutton.refinedstorage.detector.mode.2": "Emit signal when above the amount", "sidebutton.refinedstorage.constructor.drop": "Drop blocks instead of placing", "sidebutton.refinedstorage.destructor.pickup": "Pickup items instead of breaking", "sidebutton.refinedstorage.access_type": "Access type", "sidebutton.refinedstorage.access_type.0": "Insert and extract", "sidebutton.refinedstorage.access_type.1": "Insert only", "sidebutton.refinedstorage.access_type.2": "Extract only", "block.refinedstorage.controller": "Controller", "block.refinedstorage.creative_controller": "Creative Controller", "block.refinedstorage.cable": "Cable", "block.refinedstorage.grid": "Grid", "block.refinedstorage.crafting_grid": "Crafting Grid", "block.refinedstorage.pattern_grid": "Pattern Grid", "block.refinedstorage.fluid_grid": "Fluid Grid", "block.refinedstorage.disk_drive": "Disk Drive", "block.refinedstorage.disk_manipulator": "Disk Manipulator", "block.refinedstorage.external_storage": "External Storage", "block.refinedstorage.importer": "Importer", "block.refinedstorage.exporter": "Exporter", "block.refinedstorage.detector": "Detector", "block.refinedstorage.machine_casing": "Machine Casing", "block.refinedstorage.destructor": "Destructor", "block.refinedstorage.constructor": "Constructor", "block.refinedstorage.1k_storage_block": "1k Storage Block", "block.refinedstorage.4k_storage_block": "4k Storage Block", "block.refinedstorage.16k_storage_block": "16k Storage Block", "block.refinedstorage.64k_storage_block": "64k Storage Block", "block.refinedstorage.creative_storage_block": "Creative Storage Block", "block.refinedstorage.relay": "Relay", "block.refinedstorage.interface": "Interface", "block.refinedstorage.crafting_monitor": "Crafting Monitor", "block.refinedstorage.wireless_transmitter": "Wireless Transmitter", "block.refinedstorage.crafter": "Crafter", "block.refinedstorage.network_receiver": "Network Receiver", "block.refinedstorage.network_transmitter": "Network Transmitter", "block.refinedstorage.fluid_interface": "Fluid Interface", "block.refinedstorage.64k_fluid_storage_block": "64k Fluid Storage Block", "block.refinedstorage.256k_fluid_storage_block": "256k Fluid Storage Block", "block.refinedstorage.1024k_fluid_storage_block": "1024k Fluid Storage Block", "block.refinedstorage.4096k_fluid_storage_block": "4096k Fluid Storage Block", "block.refinedstorage.creative_fluid_storage_block": "Creative Fluid Storage Block", "block.refinedstorage.security_manager": "Security Manager", "block.refinedstorage.quartz_enriched_iron_block": "Block of Quartz Enriched Iron", "block.refinedstorage.storage_monitor": "Storage Monitor", "block.refinedstorage.portable_grid": "Portable Grid", "block.refinedstorage.creative_portable_grid": "Creative Portable Grid", "block.refinedstorage.portable_grid.tooltip": "Sneak to place in the world.", "block.refinedstorage.crafter_manager": "Crafter Manager", "item.refinedstorage.1k_storage_disk": "1k Storage Disk", "item.refinedstorage.4k_storage_disk": "4k Storage Disk", "item.refinedstorage.16k_storage_disk": "16k Storage Disk", "item.refinedstorage.64k_storage_disk": "64k Storage Disk", "item.refinedstorage.creative_storage_disk": "Creative Storage Disk", "item.refinedstorage.64k_fluid_storage_disk": "64k Fluid Storage Disk", "item.refinedstorage.256k_fluid_storage_disk": "256k Fluid Storage Disk", "item.refinedstorage.1024k_fluid_storage_disk": "1024k Fluid Storage Disk", "item.refinedstorage.4096k_fluid_storage_disk": "4096k Fluid Storage Disk", "item.refinedstorage.creative_fluid_storage_disk": "Creative Fluid Storage Disk", "item.refinedstorage.wireless_grid": "Wireless Grid", "item.refinedstorage.creative_wireless_grid": "Creative Wireless Grid", "item.refinedstorage.wireless_fluid_grid": "Wireless Fluid Grid", "item.refinedstorage.creative_wireless_fluid_grid": "Creative Wireless Fluid Grid", "item.refinedstorage.wireless_crafting_monitor": "Wireless Crafting Monitor", "item.refinedstorage.creative_wireless_crafting_monitor": "Creative Wireless Crafting Monitor", "item.refinedstorage.quartz_enriched_iron": "Quartz Enriched Iron", "item.refinedstorage.construction_core": "Construction Core", "item.refinedstorage.destruction_core": "Destruction Core", "item.refinedstorage.silicon": "Silicon", "item.refinedstorage.raw_basic_processor": "Raw Basic Processor", "item.refinedstorage.raw_improved_processor": "Raw Improved Processor", "item.refinedstorage.raw_advanced_processor": "Raw Advanced Processor", "item.refinedstorage.basic_processor": "Basic Processor", "item.refinedstorage.improved_processor": "Improved Processor", "item.refinedstorage.advanced_processor": "Advanced Processor", "item.refinedstorage.1k_storage_part": "1k Storage Part", "item.refinedstorage.4k_storage_part": "4k Storage Part", "item.refinedstorage.16k_storage_part": "16k Storage Part", "item.refinedstorage.64k_storage_part": "64k Storage Part", "item.refinedstorage.64k_fluid_storage_part": "64k Fluid Storage Part", "item.refinedstorage.256k_fluid_storage_part": "256k Fluid Storage Part", "item.refinedstorage.1024k_fluid_storage_part": "1024k Fluid Storage Part", "item.refinedstorage.4096k_fluid_storage_part": "4096k Fluid Storage Part", "item.refinedstorage.pattern": "Pattern", "item.refinedstorage.upgrade": "Upgrade", "item.refinedstorage.range_upgrade": "Range Upgrade", "item.refinedstorage.speed_upgrade": "Speed Upgrade", "item.refinedstorage.crafting_upgrade": "Crafting Upgrade", "item.refinedstorage.stack_upgrade": "Stack Upgrade", "item.refinedstorage.silk_touch_upgrade": "Silk Touch Upgrade", "item.refinedstorage.fortune_1_upgrade": "Fortune Upgrade", "item.refinedstorage.fortune_2_upgrade": "Fortune Upgrade", "item.refinedstorage.fortune_3_upgrade": "Fortune Upgrade", "item.refinedstorage.regulator_upgrade": "Regulator Upgrade", "item.refinedstorage.storage_housing": "Storage Housing", "item.refinedstorage.filter": "Filter", "item.refinedstorage.network_card": "Network Card", "item.refinedstorage.wrench": "Wrench", "item.refinedstorage.security_card": "Security Card", "item.refinedstorage.security_card.owner": "Bound to: %s", "item.refinedstorage.processor_binding": "Processor Binding", "item.refinedstorage.cover": "Cover", "item.refinedstorage.hollow_cover": "Hollow Cover", "commands.refinedstorage.disk.create.error.disk_not_found": "Disk %s was not found.", "commands.refinedstorage.disk.create.success": "Successfully gave disk %s to %s.", "commands.refinedstorage.network.list.pos": "Network at X: %d, Y: %d, Z: %d", "commands.refinedstorage.network.list.tick_times": "Mean tick time: %s ms. Mean TPS: %s", "commands.refinedstorage.network.list.autocrafting_tasks": "%s tasks", "commands.refinedstorage.network.list.nodes": "%s nodes", "commands.refinedstorage.network.list.energy_usage": "Energy usage: %s", "commands.refinedstorage.network.get.error.not_found": "Network not found.", "commands.refinedstorage.network.autocrafting.get.error.not_found": "Task not found.", "commands.refinedstorage.network.autocrafting.cancel.single": "Cancelled %d task.", "commands.refinedstorage.network.autocrafting.cancel.multiple": "Cancelled %d tasks.", "advancements.refinedstorage.controlling.description": "Craft a Controller", "advancements.refinedstorage.connecting": "Connecting", "advancements.refinedstorage.connecting.description": "You can place all the devices next to each other to connect them up, or, use Cable", "advancements.refinedstorage.conditional_connecting": "Conditional connecting", "advancements.refinedstorage.conditional_connecting.description": "Craft a Relay to control if a network signal can pass with redstone", "advancements.refinedstorage.drives": "Drives", "advancements.refinedstorage.drives.description": "Craft a Disk Drive to be able to store your disks", "advancements.refinedstorage.manipulating_disks": "Manipulating disks", "advancements.refinedstorage.manipulating_disks.description": "Use a Disk Manipulator to easily modify contents of disks", "advancements.refinedstorage.storing_items": "Storing items", "advancements.refinedstorage.storing_items.description": "Craft a Storage Disk and put it in your Disk Drive", "advancements.refinedstorage.viewing_items": "Viewing items", "advancements.refinedstorage.viewing_items.description": "Craft a Grid to interact with your item storage", "advancements.refinedstorage.portable_storage": "Portable storage", "advancements.refinedstorage.portable_storage.description": "Craft a Portable Grid to access items and fluids in disks without being in a network", "advancements.refinedstorage.upgrading_your_grid": "Upgrading your Grid", "advancements.refinedstorage.upgrading_your_grid.description": "Upgrade your Grid to a Crafting Grid to get crafting abilities in your Grid", "advancements.refinedstorage.storing_fluids": "Storing fluids", "advancements.refinedstorage.storing_fluids.description": "Craft a Fluid Storage Disk and put it in your Disk Drive", "advancements.refinedstorage.viewing_fluids": "Viewing fluids", "advancements.refinedstorage.viewing_fluids.description": "Craft a Fluid Grid to interact with your fluid storage", "advancements.refinedstorage.better_than_a_barrel": "Better than a barrel", "advancements.refinedstorage.better_than_a_barrel.description": "Craft a Storage Monitor to view, insert or extract items of a network", "advancements.refinedstorage.autocrafting": "Autocrafting", "advancements.refinedstorage.autocrafting.description": "Craft a Crafter", "advancements.refinedstorage.pattern_creation": "Pattern creation", "advancements.refinedstorage.pattern_creation.description": "Create patterns with a Pattern Grid and a Pattern", "advancements.refinedstorage.monitoring": "Monitoring", "advancements.refinedstorage.monitoring.description": "Check the status of your crafting tasks with a Crafting Monitor", "advancements.refinedstorage.managing_patterns": "Managing patterns", "advancements.refinedstorage.managing_patterns.description": "Craft a Crafter Manager to manage your patterns in a better way", "advancements.refinedstorage.importing": "Importing", "advancements.refinedstorage.importing.description": "Get items or fluids into the storage network with an Importer", "advancements.refinedstorage.destruction": "Destruction", "advancements.refinedstorage.destruction.description": "Get blocks or fluids into the storage network with a Destructor", "advancements.refinedstorage.exporting": "Exporting", "advancements.refinedstorage.exporting.description": "Get items or fluids out of the storage network with an Exporter", "advancements.refinedstorage.construction": "Construction", "advancements.refinedstorage.construction.description": "Get blocks or fluids out of the storage network with a Constructor", "advancements.refinedstorage.security": "Security", "advancements.refinedstorage.security.description": "Secure your network with a Security Manager and a Security Card", "advancements.refinedstorage.wireless": "Wireless", "advancements.refinedstorage.wireless.description": "Transmit a network signal with a Wireless Transmitter", "advancements.refinedstorage.wireless_items": "Wireless items", "advancements.refinedstorage.wireless_items.description": "Interact with your item storage wirelessly with a Wireless Grid", "advancements.refinedstorage.wireless_fluids": "Wireless fluids", "advancements.refinedstorage.wireless_fluids.description": "Interact with your fluid storage wirelessly with a Wireless Fluid Grid", "advancements.refinedstorage.wireless_monitoring": "Wireless monitoring", "advancements.refinedstorage.wireless_monitoring.description": "Check the status of your crafting tasks wirelessly with a Wireless Crafting Monitor", "advancements.refinedstorage.no_cables_required": "No cables required", "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", "advancements.refinedstorage.upgrading": "Upgrading", "advancements.refinedstorage.upgrading.description": "Craft an Upgrade to improve various devices", "advancements.refinedstorage.crafting_on_demand": "Crafting on demand", "advancements.refinedstorage.crafting_on_demand.description": "Use a Crafting Upgrade in a Interface, Exporter or Constructor to craft items and blocks on demand", "advancements.refinedstorage.detecting": "Detecting", "advancements.refinedstorage.detecting.description": "Detect items or fluids in the network with the Detector", "advancements.refinedstorage.interface_to_the_world": "Interface to the world", "advancements.refinedstorage.interface_to_the_world.description": "Export and import items at the same time with an Interface", "advancements.refinedstorage.storing_externally": "Storing externally", "advancements.refinedstorage.storing_externally.description": "Use an External Storage to provide the network with storage from an external block like a chest" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/es_es.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "key.refinedstorage.focusSearchBar": "Panel de búsqueda centrada", "key.refinedstorage.clearGridCraftingMatrix": "Limpiar matriz del panel de fabricación", "gui.refinedstorage.controller": "Controlador", "gui.refinedstorage.creative_controller": "Controlador creativo", "gui.refinedstorage.grid": "Panel", "gui.refinedstorage.grid.craft": "Fabricar", "gui.refinedstorage.crafting_grid": "Panel de fabricación", "gui.refinedstorage.pattern_grid": "Panel de patrones", "gui.refinedstorage.grid.pattern_create": "Crear patrón", "gui.refinedstorage.fluid_grid": "Panel de fluidos", "gui.refinedstorage.portable_grid": "Panel portátil", "gui.refinedstorage.disk_drive": "Deposito", "gui.refinedstorage.disk_drive.disks": "Depósitos", "gui.refinedstorage.external_storage": "Almacén externo", "gui.refinedstorage.importer": "Importador", "gui.refinedstorage.exporter": "Exportador", "gui.refinedstorage.detector": "Detector", "gui.refinedstorage.destructor": "Destructor", "gui.refinedstorage.constructor": "Constructor", "gui.refinedstorage.relay": "Relé", "gui.refinedstorage.interface.import": "Interfaz de entrada", "gui.refinedstorage.interface.export": "Interfaz de salida", "gui.refinedstorage.crafting_monitor": "Monitor de fabricación", "gui.refinedstorage.wireless_crafting_monitor": "Monitor remoto de fabricación", "gui.refinedstorage.crafting_monitor.machine_none": "Maquina no hallada", "gui.refinedstorage.wireless_transmitter": "Emisor inalámbrico", "gui.refinedstorage.wireless_transmitter.distance": "%d bloque(s)", "gui.refinedstorage.crafter": "Fabricador", "gui.refinedstorage.filter": "Filtro", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Filtro de mods", "gui.refinedstorage.network_transmitter": "Emisor de red", "gui.refinedstorage.network_transmitter.distance": "%d bloque(s)", "gui.refinedstorage.network_transmitter.missing_card": "Falta tarjeta de red", "gui.refinedstorage.fluid_interface": "Interfaz de fluidos", "gui.refinedstorage.fluid_interface.in": "Entrada", "gui.refinedstorage.fluid_interface.out": "Salida", "gui.refinedstorage.crafting_preview": "Avance de fabricación", "gui.refinedstorage.crafting_preview.to_craft": "Para fabricar: %d", "gui.refinedstorage.crafting_preview.available": "Disponible: %d", "gui.refinedstorage.crafting_preview.missing": "Falta: %d", "gui.refinedstorage.crafting_preview.error": "No puede fabricar", "gui.refinedstorage.crafting_preview.error.recursive.0": "Uno de los objetos de creación termino faltando", "gui.refinedstorage.crafting_preview.error.recursive.1": "sí mismo.", "gui.refinedstorage.crafting_preview.error.recursive.2": "Necesita remover el patrón o revisarlo", "gui.refinedstorage.crafting_preview.error.recursive.3": "el patrón no se usa para la fabricación.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Patrón ofensivo:", "gui.refinedstorage.security_manager": "Centro de seguridad", "gui.refinedstorage.security_manager.configure": "Configurar", "gui.refinedstorage.security_manager.permission.0": "Insertar", "gui.refinedstorage.security_manager.permission.0.tooltip": "Insertar objetos a la red", "gui.refinedstorage.security_manager.permission.1": "Extraer", "gui.refinedstorage.security_manager.permission.1.tooltip": "Extraer objetos de la red", "gui.refinedstorage.security_manager.permission.2": "Autofabricar", "gui.refinedstorage.security_manager.permission.2.tooltip": "Comenzar, cancelar y ver tareas de fabricación", "gui.refinedstorage.security_manager.permission.3": "Modificar", "gui.refinedstorage.security_manager.permission.3.tooltip": "Abrir interfaz de bloque", "gui.refinedstorage.security_manager.permission.4": "Construir", "gui.refinedstorage.security_manager.permission.4.tooltip": "Añadir o remover disposotivos de o desde la red", "gui.refinedstorage.security_manager.permission.5": "Seguridad", "gui.refinedstorage.security_manager.permission.5.tooltip": "Abilidad de cambiar opciones de seguridad", "gui.refinedstorage.storage_monitor": "Monitor de almacén", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Uso: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Guardado: %s", "misc.refinedstorage.storage.stored_capacity": "Capacidad: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% lleno", "misc.refinedstorage.network_item.tooltip": "Enlazado a %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "No hay emisor de red en rango.", "misc.refinedstorage.network_item.not_found": "No se encontró un controlador.", "misc.refinedstorage.network_card.tooltip": "Enlazado a %d, %d, %d en %s.", "misc.refinedstorage.pattern.inputs": "Entradas", "misc.refinedstorage.pattern.outputs": "Salidas", "misc.refinedstorage.pattern.invalid": "patrón invalido", "misc.refinedstorage.security.no_permission": "No tienes permiso de realizar esa acción.", "misc.refinedstorage.start": "Empezar", "misc.refinedstorage.clear": "Limpiar", "misc.refinedstorage.set": "Poner", "misc.refinedstorage.cancel_all": "Cancelar todo", "misc.refinedstorage.priority": "Prioridad", "misc.refinedstorage.processing": "Procesándose", "misc.refinedstorage.total": "%s total", "misc.refinedstorage.last_modified.just_now": "Último cambio justo ahora por %s", "misc.refinedstorage.last_modified.second": "Último cambio %d hace un segundo por %s", "misc.refinedstorage.last_modified.seconds": "Último cambio %d hace unos segundos por %s", "misc.refinedstorage.last_modified.minute": "Último cambio %d hace un minuto por %s", "misc.refinedstorage.last_modified.minutes": "Último cambio %d hace unos minutos por %s", "misc.refinedstorage.last_modified.hour": "Último cambio %d hace una hora por %s", "misc.refinedstorage.last_modified.hours": "Último cambio %d hace unas horas por %s", "misc.refinedstorage.last_modified.day": "Último cambio %d hace una día por %s", "misc.refinedstorage.last_modified.days": "Último cambio %d hace unos días por %s", "misc.refinedstorage.last_modified.week": "Último cambio %d hace una semana por %s", "misc.refinedstorage.last_modified.weeks": "Último cambio %d hace semanas por %s", "misc.refinedstorage.last_modified.year": "Último cambio %d hace un año por %s", "misc.refinedstorage.last_modified.years": "Último cambio %d hace años por %s", "sidebutton.refinedstorage.redstone_mode": "Modo de señal", "sidebutton.refinedstorage.redstone_mode.0": "Ignorar señal de redstone", "sidebutton.refinedstorage.redstone_mode.1": "Trabajar solo con señal de redstone", "sidebutton.refinedstorage.redstone_mode.2": "Trabajar solo sin señal de redstone", "sidebutton.refinedstorage.grid.view_type": "Pantalla", "sidebutton.refinedstorage.grid.view_type.0": "Normal", "sidebutton.refinedstorage.grid.view_type.1": "No fabricable", "sidebutton.refinedstorage.grid.view_type.2": "Solo fabricable", "sidebutton.refinedstorage.grid.sorting.direction": "Dirección de orden", "sidebutton.refinedstorage.grid.sorting.direction.0": "Ascendente", "sidebutton.refinedstorage.grid.sorting.direction.1": "Descendente", "sidebutton.refinedstorage.grid.sorting.type": "Tipo de orden", "sidebutton.refinedstorage.grid.sorting.type.0": "Cantidad", "sidebutton.refinedstorage.grid.sorting.type.1": "Nombre", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Último cambio", "sidebutton.refinedstorage.grid.search_box_mode": "Modo de caja de búsqueda", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normal (autoselección)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Sincronizado con JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Sincronizado con JEI (autoselección)", "sidebutton.refinedstorage.grid.size": "Tamaño", "sidebutton.refinedstorage.grid.size.0": "Tramo", "sidebutton.refinedstorage.grid.size.1": "Pequeño", "sidebutton.refinedstorage.grid.size.2": "Mediano", "sidebutton.refinedstorage.grid.size.3": "Largo", "sidebutton.refinedstorage.mode": "Modo", "sidebutton.refinedstorage.mode.whitelist": "Permitido", "sidebutton.refinedstorage.mode.blacklist": "No permitido", "sidebutton.refinedstorage.iomode": "Modo de E/S", "sidebutton.refinedstorage.iomode.insert": "Insertar a la red", "sidebutton.refinedstorage.iomode.extract": "Extraer de la red", "sidebutton.refinedstorage.type": "Tipo", "sidebutton.refinedstorage.type.0": "Objetos", "sidebutton.refinedstorage.type.1": "Fluidos", "sidebutton.refinedstorage.detector.mode": "Modo", "sidebutton.refinedstorage.detector.mode.0": "Emitir señal si hay menos de lo indicado", "sidebutton.refinedstorage.detector.mode.1": "Emitir señal si la cantidad se alcanza", "sidebutton.refinedstorage.detector.mode.2": "Emitir señal si esta más de lo indicado", "sidebutton.refinedstorage.constructor.drop": "Soltar bloques en lugar de colocar", "sidebutton.refinedstorage.destructor.pickup": "Recoger objetos en lugar de romper", "sidebutton.refinedstorage.access_type": "Tipo de acceso", "sidebutton.refinedstorage.access_type.0": "Insertar y extraer", "sidebutton.refinedstorage.access_type.1": "Solo insertar", "sidebutton.refinedstorage.access_type.2": "Solo extraer", "block.refinedstorage.controller": "Controlador", "block.refinedstorage.creative_controller": "Controlador creativo", "block.refinedstorage.cable": "Cable", "block.refinedstorage.grid": "Panel", "block.refinedstorage.crafting_grid": "Panel de fabricación", "block.refinedstorage.pattern_grid": "Panel de patrones", "block.refinedstorage.fluid_grid": "Panel de fluidos", "block.refinedstorage.disk_drive": "Almacén de discos", "block.refinedstorage.disk_manipulator": "Manipulador de discos", "block.refinedstorage.external_storage": "Almacén externo", "block.refinedstorage.importer": "Importador", "block.refinedstorage.exporter": "Exportador", "block.refinedstorage.detector": "Detector", "block.refinedstorage.machine_casing": "Estructura de maquina", "block.refinedstorage.destructor": "Destructor", "block.refinedstorage.constructor": "Constructor", "block.refinedstorage.1k_storage_block": "Bloque de memoria de 1k", "block.refinedstorage.4k_storage_block": "Bloque de memoria de 4k", "block.refinedstorage.16k_storage_block": "Bloque de memoria de 16k", "block.refinedstorage.64k_storage_block": "Bloque de memoria de 64k", "block.refinedstorage.creative_storage_block": "Bloque de memoria creativo", "block.refinedstorage.relay": "Relé", "block.refinedstorage.interface": "Interfaz", "block.refinedstorage.crafting_monitor": "Monitor de fabricación", "block.refinedstorage.wireless_transmitter": "Transmisor inalámbrico", "block.refinedstorage.wireless_transmitter.tooltip": "Necesita ser puesto en %s.", "block.refinedstorage.crafter": "Fabricador", "block.refinedstorage.network_receiver": "Receptor de red", "block.refinedstorage.network_transmitter": "Transmisor de red", "block.refinedstorage.fluid_interface": "Interfaz de fluidos", "block.refinedstorage.64k_fluid_storage_block": "Bloque de memoria de fluidos de 64k", "block.refinedstorage.256k_fluid_storage_block": "Bloque de memoria de fluidos de 256k", "block.refinedstorage.1024k_fluid_storage_block": "Bloque de memoria de fluidos de 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Bloque de memoria de fluidos de 4096k", "block.refinedstorage.creative_fluid_storage_block": "Bloque de memoria de fluidos creativo", "block.refinedstorage.security_manager": "Centro de seguridad", "block.refinedstorage.quartz_enriched_iron_block": "Bloque de hierro enriquecido con cuarzo", "block.refinedstorage.storage_monitor": "Monitor de almacén", "block.refinedstorage.portable_grid": "Panel portátil", "block.refinedstorage.creative_portable_grid": "Panel portátil creativo", "block.refinedstorage.portable_grid.tooltip": "Agáchate para colocarlo.", "item.refinedstorage.1k_storage_disk": "Disco duro de 1k", "item.refinedstorage.4k_storage_disk": "Disco duro de 4k", "item.refinedstorage.16k_storage_disk": "Disco duro de 16k", "item.refinedstorage.64k_storage_disk": "Disco duro de 64k", "item.refinedstorage.creative_storage_disk": "Disco duro creativo", "item.refinedstorage.64k_fluid_storage_disk": "Disco duro de fluidos de 64k", "item.refinedstorage.256k_fluid_storage_disk": "Disco duro de fluidos de 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Disco duro de fluidos de 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Disco duro de fluidos de 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Disco duro de fluidos creativo", "item.refinedstorage.wireless_grid": "Panel inalámbrico", "item.refinedstorage.creative_wireless_grid": "Panel inalámbrico creativo", "item.refinedstorage.wireless_fluid_grid": "Panel de fluidos inalámbrico", "item.refinedstorage.creative_wireless_fluid_grid": "Panel de fluidos inalámbrico creativo", "item.refinedstorage.wireless_crafting_monitor": "Monitor de fabricación inalámbrico", "item.refinedstorage.creative_wireless_crafting_monitor": "Monitor de fabricación inalámbrico creativo", "item.refinedstorage.quartz_enriched_iron": "Hierro enriquecido con cuarzo", "item.refinedstorage.construction_core": "Núcleo de construcción", "item.refinedstorage.destruction_core": "Núcleo de destrucción", "item.refinedstorage.silicon": "Silicio", "item.refinedstorage.basic_processor": "Procesador básico", "item.refinedstorage.improved_processor": "Procesador mejorado", "item.refinedstorage.advanced_processor": "Procesador avanzado", "item.refinedstorage.1k_storage_part": "Parte de memoria de 1k", "item.refinedstorage.4k_storage_part": "Parte de memoria de 4k", "item.refinedstorage.16k_storage_part": "Parte de memoria de 16k", "item.refinedstorage.64k_storage_part": "Parte de memoria de 64k", "item.refinedstorage.64k_fluid_storage_part": "Parte de memoria de fluidos de 64k", "item.refinedstorage.256k_fluid_storage_part": "Parte de memoria de fluidos de 256k", "item.refinedstorage.1024k_fluid_storage_part": "Parte de memoria de fluidos de 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Parte de memoria de fluidos de 4096k", "item.refinedstorage.pattern": "Patrón", "item.refinedstorage.upgrade": "Mejora", "item.refinedstorage.range_upgrade": "Mejora de rango", "item.refinedstorage.speed_upgrade": "Mejora de rapidez", "item.refinedstorage.crafting_upgrade": "Mejora de fabricación", "item.refinedstorage.stack_upgrade": "Mejora de apilación", "item.refinedstorage.silk_touch_upgrade": "Mejora de toque de seda", "item.refinedstorage.fortune_1_upgrade": "Mejora de fortuna", "item.refinedstorage.fortune_2_upgrade": "Mejora de fortuna", "item.refinedstorage.fortune_3_upgrade": "Mejora de fortuna", "item.refinedstorage.storage_housing": "Carcasa", "item.refinedstorage.filter": "Filtro", "item.refinedstorage.network_card": "Tarjeta de red", "item.refinedstorage.wrench": "Llave inglesa", "item.refinedstorage.security_card": "Tarjeta de seguridad", "item.refinedstorage.security_card.owner": "Designado a: %s", "advancements.refinedstorage.controlling.description": "Haz un controlador", "advancements.refinedstorage.connecting": "conectándose", "advancements.refinedstorage.connecting.description": "Puedes poner todos los dispositivos juntos para conectarlos, o, usa cable", "advancements.refinedstorage.conditional_connecting": "Conexión condicional", "advancements.refinedstorage.conditional_connecting.description": "Haz un relé para controlar si señal de red pasa con redstone", "advancements.refinedstorage.drives": "Almacén", "advancements.refinedstorage.drives.description": "Haz un almacén de discos para almacenar tus discos", "advancements.refinedstorage.manipulating_disks": "Manipulando discos", "advancements.refinedstorage.manipulating_disks.description": "Use un manipulador de discos para modificar los datos en discos", "advancements.refinedstorage.storing_items": "Almacenando objetos", "advancements.refinedstorage.storing_items.description": "Haz un disco duro y colocalo en el almacén", "advancements.refinedstorage.viewing_items": "Viendo objetos", "advancements.refinedstorage.viewing_items.description": "Haz un panel para interactuar con tus objetos almacenados", "advancements.refinedstorage.portable_storage": "Almacén portátil", "advancements.refinedstorage.upgrading_your_grid": "Mejorando el panel", "advancements.refinedstorage.upgrading_your_grid.description": "Mejora tu panel a uno de panel de fabricación para fabricar y ver objetos", "advancements.refinedstorage.storing_fluids": "Guardando fluidos", "advancements.refinedstorage.storing_fluids.description": "Haz un disco duro de fluidos y colocalo en el almacén de discos", "advancements.refinedstorage.viewing_fluids": "Viendo flujo", "advancements.refinedstorage.viewing_fluids.description": "Haz un panel de fluidos para interactuar con tu almacén de fluidos", "advancements.refinedstorage.better_than_a_barrel": "Mejor que un barril", "advancements.refinedstorage.better_than_a_barrel.description": "Haz un monitor de almacén para ver, insertar o extraer objetos de la red", "advancements.refinedstorage.autocrafting": "Autofabricación", "advancements.refinedstorage.autocrafting.description": "Fabrica un fabricador", "advancements.refinedstorage.pattern_creation": "Creación de patrones", "advancements.refinedstorage.pattern_creation.description": "Crea patrones usando un panel de patrones y un patrón", "advancements.refinedstorage.monitoring": "Monitoreo", "advancements.refinedstorage.monitoring.description": "Verifica el estado de las tareas de fabricación con un monitor de fabricación", "advancements.refinedstorage.importing": "Importando", "advancements.refinedstorage.importing.description": "Inserta objetos o fluidos a la red con un importador", "advancements.refinedstorage.destruction": "Destrucción", "advancements.refinedstorage.destruction.description": "Inserta bloques o fluidos a la red con un destructor", "advancements.refinedstorage.exporting": "Exportando", "advancements.refinedstorage.exporting.description": "Saca objetos o fluidos de la red con un exportador", "advancements.refinedstorage.construction": "Construcción", "advancements.refinedstorage.construction.description": "Saca bloques o fluidos de la red con un constructor", "advancements.refinedstorage.security": "Seguridad", "advancements.refinedstorage.security.description": "Asegura tu red con un centro de seguridad y una tarjeta de seguridad", "advancements.refinedstorage.wireless": "Wi-FI", "advancements.refinedstorage.wireless.description": "Transmite la señal de tu red con un transmisor de red", "advancements.refinedstorage.wireless_items": "Objetos inalámbrico", "advancements.refinedstorage.wireless_items.description": "Interactua con tus objetos guardados inalámbricamente con tu panel inalámbrico", "advancements.refinedstorage.wireless_fluids": "fluidos inalámbricos", "advancements.refinedstorage.wireless_fluids.description": "Interactua con tus fluidos guardados inalámbricamente con tu panel de fluidos inalámbrico", "advancements.refinedstorage.wireless_monitoring": "Ojos en la red", "advancements.refinedstorage.wireless_monitoring.description": "Verifica el estado de las tareas de fabricación inalámbricamente con el monitor de fabricación inalámbrico", "advancements.refinedstorage.no_cables_required": "¿para qué cables?", "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", "advancements.refinedstorage.upgrading": "Mejorando", "advancements.refinedstorage.upgrading.description": "Haz una mejora", "advancements.refinedstorage.better_range": "Mas rango", "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", "advancements.refinedstorage.crafting_on_demand": "Pedido a domicilio", "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", "advancements.refinedstorage.detecting": "Detectando", "advancements.refinedstorage.detecting.description": "Detecta objetos o fluidos en la red con el detector", "advancements.refinedstorage.interface_to_the_world": "Interfaz al mundo", "advancements.refinedstorage.storing_externally": "Almacén externo", "advancements.refinedstorage.storing_externally.description": "Usa un almacén externo para que la red tenga almacenamiento desde un bloque externo como un cofre" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/fr_fr.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "key.refinedstorage.focusSearchBar": "Barre de recherche de la grille", "gui.refinedstorage.controller": "Contrôleur", "gui.refinedstorage.creative_controller": "Contrôleur", "gui.refinedstorage.grid": "Grille", "gui.refinedstorage.grid.craft": "Craft", "gui.refinedstorage.crafting_grid": "Grille pour les crafts", "gui.refinedstorage.pattern_grid": "Grille de modèle", "gui.refinedstorage.grid.pattern_create": "Créer des modèles", "gui.refinedstorage.fluid_grid": "Grille des fluides", "gui.refinedstorage.portable_grid": "Grille portable", "gui.refinedstorage.disk_drive": "Lecteur de disques", "gui.refinedstorage.disk_drive.disks": "Disques", "gui.refinedstorage.external_storage": "Stockage externe", "gui.refinedstorage.importer": "Importeur", "gui.refinedstorage.exporter": "Exporteur", "gui.refinedstorage.detector": "Detecteur", "gui.refinedstorage.destructor": "Destructeur", "gui.refinedstorage.constructor": "Constructeur", "gui.refinedstorage.relay": "Relais", "gui.refinedstorage.interface.import": "Interface d'import", "gui.refinedstorage.interface.export": "Interface d'export", "gui.refinedstorage.crafting_monitor": "Moniteur de craft", "gui.refinedstorage.wireless_crafting_monitor": "Moniteur de craft sans-fil", "gui.refinedstorage.crafting_monitor.machine_none": "Pas de machine disponible", "gui.refinedstorage.wireless_transmitter": "Emetteur sans-fil", "gui.refinedstorage.wireless_transmitter.distance": "%d bloc(s)", "gui.refinedstorage.crafter": "Crafteur", "gui.refinedstorage.filter": "Filtre", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Filtre de mod", "gui.refinedstorage.network_transmitter": "Emetteur réseau", "gui.refinedstorage.network_transmitter.distance": "%d bloc(s)", "gui.refinedstorage.network_transmitter.missing_card": "Carte réseau manquante", "gui.refinedstorage.fluid_interface": "Interface de fluides", "gui.refinedstorage.fluid_interface.in": "Entrée", "gui.refinedstorage.fluid_interface.out": "Sortie", "gui.refinedstorage.crafting_preview": "Aperçu de craft", "gui.refinedstorage.crafting_preview.to_craft": "A craft: %d", "gui.refinedstorage.crafting_preview.available": "Disponible: %d", "gui.refinedstorage.crafting_preview.missing": "Manquant: %d", "gui.refinedstorage.crafting_preview.circular": "Dépendance circulaire!", "gui.refinedstorage.crafting_preview.loop": "Boucle de traitement...", "gui.refinedstorage.security_manager": "Poste de sécurité", "gui.refinedstorage.security_manager.configure": "Configure", "gui.refinedstorage.security_manager.permission.0": "Insère", "gui.refinedstorage.security_manager.permission.0.tooltip": "Insertion d'items dans le réseau", "gui.refinedstorage.security_manager.permission.1": "Extrait", "gui.refinedstorage.security_manager.permission.1.tooltip": "Extraction d'items du réseau", "gui.refinedstorage.security_manager.permission.2": "Autocraft", "gui.refinedstorage.security_manager.permission.2.tooltip": "Lance, annule et voit les taches de crafts", "gui.refinedstorage.security_manager.permission.3": "Modifie", "gui.refinedstorage.security_manager.permission.3.tooltip": "Ouvre l'interface des blocks", "gui.refinedstorage.security_manager.permission.4": "Construit", "gui.refinedstorage.security_manager.permission.4.tooltip": "Ajoute ou enlève des appareils sur le réseau", "gui.refinedstorage.security_manager.permission.5": "Securité", "gui.refinedstorage.security_manager.permission.5.tooltip": "Capable de modifier les options de sécurité", "gui.refinedstorage.storage_monitor": "Storage moniteur", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Usage: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Stored: %s", "misc.refinedstorage.storage.stored_capacity": "Stored: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% plein", "misc.refinedstorage.network_item.tooltip": "Linked to %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Pas d'émetteur sans-fil à portée.", "misc.refinedstorage.network_item.not_found": "Controlleur introuvable.", "misc.refinedstorage.network_card.tooltip": "Linked to %d, %d, %d in %s.", "misc.refinedstorage.pattern.inputs": "Entrée", "misc.refinedstorage.pattern.outputs": "Sortie", "misc.refinedstorage.pattern.invalid": "Modèle invalide", "misc.refinedstorage.security.no_permission": "Vous n'avez pas l'autorisation de faire cette action.", "misc.refinedstorage.start": "Commencer", "misc.refinedstorage.clear": "Vider", "misc.refinedstorage.set": "Fixer", "misc.refinedstorage.cancel_all": "Tout annuler", "misc.refinedstorage.priority": "Priorité", "misc.refinedstorage.processing": "En traitement", "sidebutton.refinedstorage.redstone_mode": "Mode redstone", "sidebutton.refinedstorage.redstone_mode.0": "Ignore le signal de redstone", "sidebutton.refinedstorage.redstone_mode.1": "Actif seulement avec signal de redstone", "sidebutton.refinedstorage.redstone_mode.2": "Actif seulement sans signal de redstone", "sidebutton.refinedstorage.grid.view_type": "Affiche", "sidebutton.refinedstorage.grid.view_type.0": "Normal", "sidebutton.refinedstorage.grid.view_type.1": "Pas de craftables", "sidebutton.refinedstorage.grid.view_type.2": "Seulement les craftables", "sidebutton.refinedstorage.grid.sorting.direction": "Ordre de tri", "sidebutton.refinedstorage.grid.sorting.direction.0": "Croissant", "sidebutton.refinedstorage.grid.sorting.direction.1": "Décroissant", "sidebutton.refinedstorage.grid.sorting.type": "Type de tri", "sidebutton.refinedstorage.grid.sorting.type.0": "Quantité", "sidebutton.refinedstorage.grid.sorting.type.1": "Nom", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.search_box_mode": "Mode de la barre de recherche", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normal (sélection auto)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Synchronisé JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Synchronisé JEI (sélection auto)", "sidebutton.refinedstorage.grid.size": "Taille", "sidebutton.refinedstorage.grid.size.0": "Etendu", "sidebutton.refinedstorage.grid.size.1": "Petit", "sidebutton.refinedstorage.grid.size.2": "Moyen", "sidebutton.refinedstorage.grid.size.3": "Grand", "sidebutton.refinedstorage.mode": "Mode", "sidebutton.refinedstorage.mode.whitelist": "Liste blanche", "sidebutton.refinedstorage.mode.blacklist": "Liste noire", "sidebutton.refinedstorage.iomode": "IO mode", "sidebutton.refinedstorage.iomode.insert": "Insère dans le réseau", "guidebutton.refinedstorage.iomode.extract": "Extrait du réseau", "sidebutton.refinedstorage.type": "Type", "sidebutton.refinedstorage.type.0": "Items", "sidebutton.refinedstorage.type.1": "Fluides", "sidebutton.refinedstorage.detector.mode": "Mode", "sidebutton.refinedstorage.detector.mode.0": "Emet un signal quand la quantité est inférieure", "sidebutton.refinedstorage.detector.mode.1": "Emet un signal quand la quantité est égale", "sidebutton.refinedstorage.detector.mode.2": "Emet un signal quand la quantité est supérieure", "sidebutton.refinedstorage.constructor.drop": "Laisse tomber les blocs au lieu de les placer", "sidebutton.refinedstorage.destructor.pickup": "Ramasse les items au lieu de les casser", "sidebutton.refinedstorage.access_type": "Type d'accès", "sidebutton.refinedstorage.access_type.0": "Insère and extrait", "sidebutton.refinedstorage.access_type.1": "Insère seulement", "sidebutton.refinedstorage.access_type.2": "Extrait seulement", "block.refinedstorage.controller": "Controlleur", "block.refinedstorage.creative_controller": "Controlleur créatif", "block.refinedstorage.cable": "Cable", "block.refinedstorage.grid": "Grille", "block.refinedstorage.crafting_grid": "Grille de craft", "block.refinedstorage.pattern_grid": "Grille de modèle", "block.refinedstorage.fluid_grid": "Grille de fluide", "block.refinedstorage.disk_drive": "Lecteur de disque", "block.refinedstorage.disk_manipulator": "Manipulateur de disque", "block.refinedstorage.external_storage": "Stockage externe", "block.refinedstorage.importer": "Importeur", "block.refinedstorage.exporter": "Exporteur", "block.refinedstorage.detector": "Detecteur", "block.refinedstorage.machine_casing": "Boitier de machine", "block.refinedstorage.destructor": "Destructeur", "block.refinedstorage.constructor": "Constructeur", "block.refinedstorage.1k_storage_block": "Bloc de stockage 1k", "block.refinedstorage.4k_storage_block": "Bloc de stockage 4k", "block.refinedstorage.16k_storage_block": "Bloc de stockage 16k", "block.refinedstorage.64k_storage_block": "Bloc de stockage 64k", "block.refinedstorage.creative_storage_block": "Bloc de stockage créatif", "block.refinedstorage.relay": "Relais", "block.refinedstorage.interface": "Interface", "block.refinedstorage.crafting_monitor": "Moniteur de craft", "block.refinedstorage.wireless_transmitter": "Emetteur sans fil", "block.refinedstorage.wireless_transmitter.tooltip": "A besoin d'être placé sur %s.", "block.refinedstorage.crafter": "Crafteur", "block.refinedstorage.network_receiver": "Récepteur réseau", "block.refinedstorage.network_transmitter": "Transmetteur réseau", "block.refinedstorage.fluid_interface": "Interface de fluides", "block.refinedstorage.64k_fluid_storage_block": "Bloc de stockage de fluides de 64k", "block.refinedstorage.256k_fluid_storage_block": "Bloc de stockage de fluides de 256k", "block.refinedstorage.1024k_fluid_storage_block": "Bloc de stockage de fluides de 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Bloc de stockage de fluides de 4096k", "block.refinedstorage.creative_fluid_storage_block": "Bloc de stockage de fluides créatif", "block.refinedstorage.security_manager": "Poste de sécurité", "block.refinedstorage.quartz_enriched_iron_block": "Bloc de quartz enrichi au fer", "block.refinedstorage.storage_monitor": "Moniteur de stockage", "block.refinedstorage.portable_grid": "Grille portative", "block.refinedstorage.creative_portable_grid": "Grille portative créatif", "block.refinedstorage.portable_grid.tooltip": "S'accroupir pour placer dans le monde.", "item.refinedstorage.1k_storage_disk": "Disque de stockage 1k", "item.refinedstorage.4k_storage_disk": "Disque de stockage 4k", "item.refinedstorage.16k_storage_disk": "Disque de stockage 16k", "item.refinedstorage.64k_storage_disk": "Disque de stockage 64k", "item.refinedstorage.creative_storage_disk": "Disque de stockage créatif", "item.refinedstorage.64k_fluid_storage_disk": "Disque de stockage de fluides 64k", "item.refinedstorage.256k_fluid_storage_disk": "Disque de stockage de fluides 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Disque de stockage de fluides 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Disque de stockage de fluides 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Disque de stockage de fluides créatif", "item.refinedstorage.wireless_grid": "Grille sans fil", "item.refinedstorage.creative_wireless_grid": "Grille sans fil créative", "item.refinedstorage.wireless_fluid_grid": "Grille de liquide sans fil", "item.refinedstorage.creative_wireless_fluid_grid": "Grille liquide sans fil créative", "item.refinedstorage.wireless_crafting_monitor": "Moniteur de craft sans fil", "item.refinedstorage.creative_wireless_crafting_monitor": "Moniteur de craft sans fil créatif", "item.refinedstorage.quartz_enriched_iron": "Quartz enrichi au fer", "item.refinedstorage.construction_core": "Coeur de construction", "item.refinedstorage.destruction_core": "Coeur de destruction", "item.refinedstorage.silicon": "Silicone", "item.refinedstorage.basic_processor": "Processeur basique", "item.refinedstorage.improved_processor": "Processeur amélioré", "item.refinedstorage.advanced_processor": "Processeur avancé", "item.refinedstorage.1k_storage_part": "Pièce de stockage 1k", "item.refinedstorage.4k_storage_part": "Pièce de stockage 4k", "item.refinedstorage.16k_storage_part": "Pièce de stockage 16k", "item.refinedstorage.64k_storage_part": "Pièce de stockage 64k", "item.refinedstorage.64k_fluid_storage_part": "Pièce de stockage de fluides 64k", "item.refinedstorage.256k_fluid_storage_part": "Pièce de stockage de fluides 256k", "item.refinedstorage.1024k_fluid_storage_part": "Pièce de stockage de fluides 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Pièce de stockage de fluides 4096k", "item.refinedstorage.pattern": "Modèle", "item.refinedstorage.upgrade": "Amélioration", "item.refinedstorage.range_upgrade": "Amélioration de portée", "item.refinedstorage.speed_upgrade": "Amélioration de vitesse", "item.refinedstorage.crafting_upgrade": "Amélioration de craft", "item.refinedstorage.stack_upgrade": "Amélioration de stack", "item.refinedstorage.silk_touch_upgrade": "Amélioration touché de soie", "item.refinedstorage.fortune_1_upgrade": "Amélioration de fortune", "item.refinedstorage.fortune_2_upgrade": "Amélioration de fortune", "item.refinedstorage.fortune_3_upgrade": "Amélioration de fortune", "item.refinedstorage.storage_housing": "Boitier de stockage", "item.refinedstorage.filter": "Filtre", "item.refinedstorage.network_card": "Carte réseau", "item.refinedstorage.wrench": "Clé", "item.refinedstorage.security_card": "Carte de sécurité", "item.refinedstorage.security_card.owner": "Bound to: %s", "advancements.refinedstorage.controlling.description": "Craft d'un controlleur", "advancements.refinedstorage.connecting": "En cours de connexion", "advancements.refinedstorage.connecting.description": "Vous pouvez placer chaque appareil côte à côte pour les connecter ensemble, ou utiliser un cable.", "advancements.refinedstorage.conditional_connecting": "Connexion conditionnelle", "advancements.refinedstorage.conditional_connecting.description": "Crafter un relais pour controller si le signal du réseau peut passer avec un signal de redstone", "advancements.refinedstorage.drives": "Lecteur de disques", "advancements.refinedstorage.drives.description": "Crafter un lecteur de disques pour pouvoir stocker vos disques", "advancements.refinedstorage.manipulating_disks": "Disque manipulateur", "advancements.refinedstorage.manipulating_disks.description": "Utiliser un disque manipulateur pour modifier facilement le contenu des disques", "advancements.refinedstorage.storing_items": "Stocker les items", "advancements.refinedstorage.storing_items.description": "Crafter un disque et le mettre dans un lecteur", "advancements.refinedstorage.viewing_items": "Voir les items", "advancements.refinedstorage.viewing_items.description": "Crafter une grille pour intéragir avec votre stockage d'item", "advancements.refinedstorage.portable_storage": "Stockage portatif", "advancements.refinedstorage.upgrading_your_grid": "Améliorer votre grille", "advancements.refinedstorage.upgrading_your_grid.description": "Améliorer votre grille vers une grille de craft pour pouvoir crafter dans votre grille", "advancements.refinedstorage.storing_fluids": "Stocker des fluides", "advancements.refinedstorage.storing_fluids.description": "Crafte un disque de fluide et le mettre dans un lecteur", "advancements.refinedstorage.viewing_fluids": "Voir les fluides", "advancements.refinedstorage.viewing_fluids.description": "Crafter une grille pour intéragir avec votre stockage de fluides", "advancements.refinedstorage.better_than_a_barrel": "Mieux qu'un barril", "advancements.refinedstorage.better_than_a_barrel.description": "Crafter un moniteur de stockage pour voir, insérer ou extraire des items de votre réseau", "advancements.refinedstorage.autocrafting": "Autocrafter", "advancements.refinedstorage.autocrafting.description": "Crafter un crafteur", "advancements.refinedstorage.pattern_creation": "Création de modèle", "advancements.refinedstorage.pattern_creation.description": "Créer des modèles avec la grille de modèle et un modèle", "advancements.refinedstorage.monitoring": "Controller", "advancements.refinedstorage.monitoring.description": "Vérifier le statut de vos tâches de crafts avec le moniteur de crafts", "advancements.refinedstorage.importing": "Importer", "advancements.refinedstorage.importing.description": "Amener des items ou fluides dans le réseau de stockage avec un importeur", "advancements.refinedstorage.destruction": "Destruction", "advancements.refinedstorage.destruction.description": "Amener des blocs ou fluides dans le réseau de stockage avec un destructeur", "advancements.refinedstorage.exporting": "Exporter", "advancements.refinedstorage.exporting.description": "Sortir des items ou fluides du réseau de stockage avec un exporteur", "advancements.refinedstorage.construction": "Construction", "advancements.refinedstorage.construction.description": "Sortir des blocs ou fluides du réseau de stockage avec un constructeur", "advancements.refinedstorage.security": "Sécurité", "advancements.refinedstorage.security.description": "Securisez votre réseau avec un poste de sécurité et une carte de sécurité", "advancements.refinedstorage.wireless": "Sans fil", "advancements.refinedstorage.wireless.description": "Transmettez un signal réseau avec un émetteur sans fil", "advancements.refinedstorage.wireless_items": "Items sans fil", "advancements.refinedstorage.wireless_items.description": "Interagissez avec votre stockage d'items a distance avec votre grille sans fil", "advancements.refinedstorage.wireless_fluids": "Fluides sans fils", "advancements.refinedstorage.wireless_fluids.description": "Interagissez avec votre stockage de fluide à distance avec une grille de fluides sans fil", "advancements.refinedstorage.wireless_monitoring": "Controller", "advancements.refinedstorage.wireless_monitoring.description": "Controller le statut de vos taches de craft à distance avec un moniteur de crafts sans fil", "advancements.refinedstorage.no_cables_required": "Aucun cable demandé", "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", "advancements.refinedstorage.upgrading": "Amélioration", "advancements.refinedstorage.upgrading.description": "Craftez une amélioration", "advancements.refinedstorage.crafting_on_demand": "Crafter à la demande", "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", "advancements.refinedstorage.detecting": "Detection", "advancements.refinedstorage.detecting.description": "Detectez les items ou fluides dans le réseau avec un détecteur", "advancements.refinedstorage.interface_to_the_world": "Interface vers le monde", "advancements.refinedstorage.storing_externally": "Stocker éternellement", "advancements.refinedstorage.storing_externally.description": "Utilisez un stockage externe pour fournir au réseau un stockage à partir d'un bloc externe comme un coffre" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/hu_hu.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage Fedők", "key.refinedstorage.focusSearchBar": "Kereső Mező Rács Fókuszálása", "key.refinedstorage.clearGridCraftingMatrix": "Barkácsoló Mátrix Rács Ürítése", "key.refinedstorage.openWirelessGrid": "Vezeték Nélküli Rács Megnyitása", "key.refinedstorage.openWirelessFluidGrid": "Vezeték Nélküli Folyadékrács Megnyitása", "key.refinedstorage.openPortableGrid": "Hordozható Rács Megnyitása", "key.refinedstorage.openWirelessCraftingMonitor": "Vezeték Nélküli Barkácsoló Monitor Megnyitása", "gui.refinedstorage.controller": "Vezérlő", "gui.refinedstorage.creative_controller": "Kreatív Vezérlő", "gui.refinedstorage.grid": "Rács", "gui.refinedstorage.grid.craft": "Barkácsolás", "gui.refinedstorage.crafting_grid": "Barkácsoló Rács", "gui.refinedstorage.pattern_grid": "Sablon Rács", "gui.refinedstorage.grid.pattern_create": "Létrehoz", "gui.refinedstorage.fluid_grid": "Folyadék Rács", "gui.refinedstorage.portable_grid": "Hordozható Rács", "gui.refinedstorage.item_amount": "Tárgy Mennyiség", "gui.refinedstorage.fluid_amount": "Folyadék Mennyiség mB-ben", "gui.refinedstorage.disk_drive": "Lemez Meghajtó", "gui.refinedstorage.disk_drive.disks": "Lemezek", "gui.refinedstorage.disk_manipulator": "Lemez Kezelő", "gui.refinedstorage.disk_manipulator.in": "Be", "gui.refinedstorage.disk_manipulator.out": "Ki", "gui.refinedstorage.external_storage": "Külső Tárhely", "gui.refinedstorage.importer": "Importáló", "gui.refinedstorage.exporter": "Exportáló", "gui.refinedstorage.detector": "Érzékelő", "gui.refinedstorage.destructor": "Megsemmisítő", "gui.refinedstorage.constructor": "Építő", "gui.refinedstorage.relay": "Jelfogó", "gui.refinedstorage.interface.import": "Import Interfész", "gui.refinedstorage.interface.export": "Export Interfész", "gui.refinedstorage.crafting_monitor": "Barkácsoló Monitor", "gui.refinedstorage.wireless_crafting_monitor": "Vezeték Nélküli Barkácsoló Monitor", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d kérvényezve", "gui.refinedstorage.crafting_monitor.stored": "Tárolva: %d", "gui.refinedstorage.crafting_monitor.missing": "Hiányzik: %d", "gui.refinedstorage.crafting_monitor.processing": "Feldolgozás Alatt: %d", "gui.refinedstorage.crafting_monitor.scheduled": "Beütemezve: %d", "gui.refinedstorage.crafting_monitor.crafting": "Barkácsolás Alatt: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "A Gép Nem Fogadja El a Tárgyat", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "A Gép Nem Fogadja El a Folyadékot", "gui.refinedstorage.crafting_monitor.machine_none": "Nincs Gép", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Barkácsoló Lezárva", "gui.refinedstorage.wireless_transmitter": "Vezeték Nélküli Adó", "gui.refinedstorage.wireless_transmitter.distance": "%d blokk(ok)", "gui.refinedstorage.crafter": "Barkácsoló", "gui.refinedstorage.filter": "Szűrő", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Mod Szűrő", "gui.refinedstorage.network_transmitter": "Hálózati Adó", "gui.refinedstorage.network_transmitter.distance": "%d blokk(ok)", "gui.refinedstorage.network_transmitter.missing_card": "Hiányzó Hálózati Kártya", "gui.refinedstorage.fluid_interface": "Folyadék Interfész", "gui.refinedstorage.fluid_interface.in": "Be", "gui.refinedstorage.fluid_interface.out": "Ki", "gui.refinedstorage.crafting_preview": "Barkácsolási Előnézet", "gui.refinedstorage.crafting_preview.to_craft": "Barkácsolandó: %d", "gui.refinedstorage.crafting_preview.available": "Elérhető: %d", "gui.refinedstorage.crafting_preview.missing": "Hiányzik: %d", "gui.refinedstorage.crafting_preview.error": "Kérés Elutasítva", "gui.refinedstorage.crafting_preview.error.recursive.0": "Az egyik alapanyagnak szüksége volt", "gui.refinedstorage.crafting_preview.error.recursive.1": "magára.", "gui.refinedstorage.crafting_preview.error.recursive.2": "El kell távolítanod a sablont, hogy", "gui.refinedstorage.crafting_preview.error.recursive.3": "ne legyen használva barkácsoláskor.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Problémás Sablon:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "A barkácsolási számítás túl bonyolult volt,", "gui.refinedstorage.crafting_preview.error.too_complex.1": "ezért le lett állítva, hogy ne terhelje a szervert.", "gui.refinedstorage.security_manager": "Biztonsági Menedzser", "gui.refinedstorage.security_manager.configure": "Beállítások", "gui.refinedstorage.security_manager.permission.0": "Bevitel", "gui.refinedstorage.security_manager.permission.0.tooltip": "Tárgyak és Folyadékok bevitele a hálózatba", "gui.refinedstorage.security_manager.permission.1": "Kivitel", "gui.refinedstorage.security_manager.permission.1.tooltip": "Tárgyak és Folyadékok kivitele a hálózatból", "gui.refinedstorage.security_manager.permission.2": "Autobarkácsolás", "gui.refinedstorage.security_manager.permission.2.tooltip": "Barkácsoló folyamatok elkezdése, megszakítása és megfigyelése", "gui.refinedstorage.security_manager.permission.3": "Módosítás", "gui.refinedstorage.security_manager.permission.3.tooltip": "Blokkok megnyitása", "gui.refinedstorage.security_manager.permission.4": "Építés", "gui.refinedstorage.security_manager.permission.4.tooltip": "Eszközök hozzáadása és elvétele a hálózatból", "gui.refinedstorage.security_manager.permission.5": "Biztonság", "gui.refinedstorage.security_manager.permission.5.tooltip": "Engedély a biztonsági beállítások módosítására", "gui.refinedstorage.storage_monitor": "Tárhely Monitor", "gui.refinedstorage.crafter_manager": "Barkácsoló Menedzser", "gui.refinedstorage.alternatives": "Alternatívák", "gui.refinedstorage.alternatives.apply": "Alkalmaz", "gui.refinedstorage.jei.transfer.autocrafting_available": "Autobarkácsolás elérhető", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRL + CLICK autobarkácsolás kéréséhez", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMD + CLICK autobarkácsolás kéréséhez", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Fogyasztás: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Tárolva: %s", "misc.refinedstorage.storage.stored_capacity": "Tárolva: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%%-ban tele", "misc.refinedstorage.network_item.tooltip": "Csatlakoztatva %d, %d, %d-hez.", "misc.refinedstorage.network_item.out_of_range": "Nincs Vezeték Nélküli Adó a közelben.", "misc.refinedstorage.network_item.not_found": "A Hálózat nem létezik.", "misc.refinedstorage.network_item.shortcut_not_found": "Semennyi %s sincs az eszköztáradban.", "misc.refinedstorage.network_item.shortcut_duplicate": "Több mint egy %s van az eszköztáradban.", "misc.refinedstorage.network_item.out_of_energy": "A(z) %s kifogyott energiából.", "misc.refinedstorage.network_card.tooltip": "Csatlakoztatva %d, %d, %d-hez %s-ben.", "misc.refinedstorage.pattern.inputs": "Bemenetek", "misc.refinedstorage.pattern.outputs": "Kimenetek", "misc.refinedstorage.pattern.invalid": "Érvénytelen Sablon", "misc.refinedstorage.pattern.exact": "Pontos módot használ", "misc.refinedstorage.pattern.allowed_item_tag": "%s-ből használ tárgyakat %s-hez", "misc.refinedstorage.pattern.allowed_fluid_tag": "%s-ből használ folyadékokat %s-hez", "misc.refinedstorage.pattern.error.processing_no_outputs": "A feldolgozási sablonnak nincs kimenete", "misc.refinedstorage.pattern.error.no_output": "A receptnek nincs kimenete", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "A recept nem létezik", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "A %s címke többé nem alkalmazható %s-re", "misc.refinedstorage.security.no_permission": "Erre nincs felhatalmazásod.", "misc.refinedstorage.start": "Kezdés", "misc.refinedstorage.clear": "Ürítés", "misc.refinedstorage.set": "Beállít", "misc.refinedstorage.cancel_all": "MINDEN megszakítása", "misc.refinedstorage.priority": "Prioritás", "misc.refinedstorage.exact": "Pontos", "misc.refinedstorage.processing": "Feldolgozás", "misc.refinedstorage.fluidmode": "Folyadékok", "misc.refinedstorage.total": "összesen %s", "misc.refinedstorage.last_modified.just_now": "Utoljára módosítva most, %s által", "misc.refinedstorage.last_modified.second": "Utoljára módosítva %d másodperce, %s által", "misc.refinedstorage.last_modified.seconds": "Utoljára módosítva %d másodperce, %s által", "misc.refinedstorage.last_modified.minute": "Utoljára módosítva %d perce, %s által", "misc.refinedstorage.last_modified.minutes": "Utoljára módosítva %d perce, %s által", "misc.refinedstorage.last_modified.hour": "Utoljára módosítva %d órája, %s által", "misc.refinedstorage.last_modified.hours": "Utoljára módosítva %d órája, %s által", "misc.refinedstorage.last_modified.day": "Utoljára módosítva %d napja, %s által", "misc.refinedstorage.last_modified.days": "Utoljára módosítva %d napja, %s által", "misc.refinedstorage.last_modified.week": "Utoljára módosítva %d hete, %s által", "misc.refinedstorage.last_modified.weeks": "Utoljára módosítva %d hete, %s által", "misc.refinedstorage.last_modified.year": "Utoljára módosítva %d éve, %s által", "misc.refinedstorage.last_modified.years": "Utoljára módosítva %d éve, %s által", "sidebutton.refinedstorage.exact_mode": "Pontos mód", "sidebutton.refinedstorage.exact_mode.on": "Be", "sidebutton.refinedstorage.exact_mode.off": "Ki", "sidebutton.refinedstorage.redstone_mode": "Redstone mód", "sidebutton.refinedstorage.redstone_mode.0": "Redstone jel figyelmen kívül hagyása", "sidebutton.refinedstorage.redstone_mode.1": "Csak redstone jellel működjön", "sidebutton.refinedstorage.redstone_mode.2": "Csak redstone jel nélkül működjön", "sidebutton.refinedstorage.crafter_mode": "Barkácsoló mód", "sidebutton.refinedstorage.crafter_mode.0": "Redstone jel figyelmen kívül hagyása", "sidebutton.refinedstorage.crafter_mode.1": "Redstone jel feloldja az autobarkácsolást", "sidebutton.refinedstorage.crafter_mode.2": "Redstone jel lezárja az autobarkácsolást", "sidebutton.refinedstorage.crafter_mode.3": "Redstone impulzus beilleszti a következő készletet", "sidebutton.refinedstorage.grid.view_type": "Kijelző", "sidebutton.refinedstorage.grid.view_type.0": "Normál", "sidebutton.refinedstorage.grid.view_type.1": "Barkácsolhatók nélkül", "sidebutton.refinedstorage.grid.view_type.2": "Csak Barkácsolhatók", "sidebutton.refinedstorage.grid.sorting.direction": "Rendezési irány", "sidebutton.refinedstorage.grid.sorting.direction.0": "Növekvő", "sidebutton.refinedstorage.grid.sorting.direction.1": "Csökkenő", "sidebutton.refinedstorage.grid.sorting.type": "Rendezés módja", "sidebutton.refinedstorage.grid.sorting.type.0": "Mennyiség", "sidebutton.refinedstorage.grid.sorting.type.1": "Név", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Utoljára módosítva", "sidebutton.refinedstorage.grid.search_box_mode": "Kereső mező mód", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normál", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normál (automatikusan választva)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI szinkronizált", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI szinkronizált (automatikusan választva)", "sidebutton.refinedstorage.grid.search_box_mode.4": "JEI szinkronizált (kétirányú)", "sidebutton.refinedstorage.grid.search_box_mode.5": "JEI szinkronizált (kétirányú automatikusan választva)", "sidebutton.refinedstorage.grid.size": "Méret", "sidebutton.refinedstorage.grid.size.0": "Nyújtott", "sidebutton.refinedstorage.grid.size.1": "Kicsi", "sidebutton.refinedstorage.grid.size.2": "Közepes", "sidebutton.refinedstorage.grid.size.3": "Nagy", "sidebutton.refinedstorage.mode": "Mód", "sidebutton.refinedstorage.mode.whitelist": "Fehérlista", "sidebutton.refinedstorage.mode.blacklist": "Feketelista", "sidebutton.refinedstorage.iomode": "IO mód", "sidebutton.refinedstorage.iomode.insert": "Hálózatba helyezés", "sidebutton.refinedstorage.iomode.extract": "Hálózatból eltávolítás", "sidebutton.refinedstorage.type": "Típus", "sidebutton.refinedstorage.type.0": "Tárgyak", "sidebutton.refinedstorage.type.1": "Folyadékok", "sidebutton.refinedstorage.detector.mode": "Mód", "sidebutton.refinedstorage.detector.mode.0": "Jel kiadása adott mennyiség alatt", "sidebutton.refinedstorage.detector.mode.1": "Jel kiadása adott mennyiségnél", "sidebutton.refinedstorage.detector.mode.2": "Jel kiadása adott mennyiség felett", "sidebutton.refinedstorage.constructor.drop": "Blokkok kidobása lehelyezés helyett", "sidebutton.refinedstorage.destructor.pickup": "Tárgyak felvétele eltörés helyett", "sidebutton.refinedstorage.access_type": "Hozzáférés típusa", "sidebutton.refinedstorage.access_type.0": "Betétel és kivétel", "sidebutton.refinedstorage.access_type.1": "Csak betétel", "sidebutton.refinedstorage.access_type.2": "Csak kivétel", "block.refinedstorage.controller": "Vezérlő", "block.refinedstorage.creative_controller": "Kreatív Vezérlő", "block.refinedstorage.cable": "Kábel", "block.refinedstorage.grid": "Rács", "block.refinedstorage.crafting_grid": "Barkácsoló Rács", "block.refinedstorage.pattern_grid": "Sablon Rács", "block.refinedstorage.fluid_grid": "Folyadék Rács", "block.refinedstorage.disk_drive": "Lemez Meghajtó", "block.refinedstorage.disk_manipulator": "Lemez Kezelő", "block.refinedstorage.external_storage": "Külső Tárhely", "block.refinedstorage.importer": "Importáló", "block.refinedstorage.exporter": "Exportáló", "block.refinedstorage.detector": "Érzékelő", "block.refinedstorage.machine_casing": "Gépház", "block.refinedstorage.destructor": "Megsemmisítő", "block.refinedstorage.constructor": "Építő", "block.refinedstorage.1k_storage_block": "1k Tároló Blokk", "block.refinedstorage.4k_storage_block": "4k Tároló Blokk", "block.refinedstorage.16k_storage_block": "16k Tároló Blokk", "block.refinedstorage.64k_storage_block": "64k Tároló Blokk", "block.refinedstorage.creative_storage_block": "Kreatív Tároló Blokk", "block.refinedstorage.relay": "Jelfogó", "block.refinedstorage.interface": "Interfész", "block.refinedstorage.crafting_monitor": "Barkácsoló Monitor", "block.refinedstorage.wireless_transmitter": "Vezeték Nélküli Jeladó", "block.refinedstorage.crafter": "Barkácsoló", "block.refinedstorage.network_receiver": "Hálózat Jelfogadó", "block.refinedstorage.network_transmitter": "Hálózat Jeladó", "block.refinedstorage.fluid_interface": "Folyadék Interfész", "block.refinedstorage.64k_fluid_storage_block": "64k Folyadék Tároló Blokk", "block.refinedstorage.256k_fluid_storage_block": "256k Folyadék Tároló Blokk", "block.refinedstorage.1024k_fluid_storage_block": "1024k Folyadék Tároló Blokk", "block.refinedstorage.4096k_fluid_storage_block": "4096k Folyadék Tároló Blokk", "block.refinedstorage.creative_fluid_storage_block": "Kreatív Folyadék Tároló Blokk", "block.refinedstorage.security_manager": "Biztonsági Menedzser", "block.refinedstorage.quartz_enriched_iron_block": "Kvarccal Dúsított Vas Blokk", "block.refinedstorage.storage_monitor": "Tárhely Monitor", "block.refinedstorage.portable_grid": "Hordozható Rács", "block.refinedstorage.creative_portable_grid": "Kreatív Hordozható Rács", "block.refinedstorage.portable_grid.tooltip": "Lopakodj a világban elhelyezéshez.", "block.refinedstorage.crafter_manager": "Barkácsoló Menedzser", "item.refinedstorage.1k_storage_disk": "1k Tároló Lemez", "item.refinedstorage.4k_storage_disk": "4k Tároló Lemez", "item.refinedstorage.16k_storage_disk": "16k Tároló Lemez", "item.refinedstorage.64k_storage_disk": "64k Tároló Lemez", "item.refinedstorage.creative_storage_disk": "Kreatív Tároló Lemez", "item.refinedstorage.64k_fluid_storage_disk": "64k Folyadék Tároló Lemez", "item.refinedstorage.256k_fluid_storage_disk": "256k Folyadék Tároló Lemez", "item.refinedstorage.1024k_fluid_storage_disk": "1024k Folyadék Tároló Lemez", "item.refinedstorage.4096k_fluid_storage_disk": "4096k Folyadék Tároló Lemez", "item.refinedstorage.creative_fluid_storage_disk": "Kreatív Folyadék Tároló Lemez", "item.refinedstorage.wireless_grid": "Vezeték Nélküli Rács", "item.refinedstorage.creative_wireless_grid": "Kreatív Vezeték Nélküli Rács", "item.refinedstorage.wireless_fluid_grid": "Vezeték Nélküli Folyadék Rács", "item.refinedstorage.creative_wireless_fluid_grid": "Kreatív Vezeték Nélküli Folyadék Rács", "item.refinedstorage.wireless_crafting_monitor": "Vezeték Nélküli Barkácsoló Monitor", "item.refinedstorage.creative_wireless_crafting_monitor": "Kreatív Vezeték Nélküli Barkácsoló Monitor", "item.refinedstorage.quartz_enriched_iron": "Kvarccal Dúsított Vas", "item.refinedstorage.construction_core": "Építő Mag", "item.refinedstorage.destruction_core": "Megsemmisítő Mag", "item.refinedstorage.silicon": "Szilikon", "item.refinedstorage.raw_basic_processor": "Nyers Szimpla Processzor", "item.refinedstorage.raw_improved_processor": "Nyers Javított Processzor", "item.refinedstorage.raw_advanced_processor": "Nyers Fejlett Processzor", "item.refinedstorage.basic_processor": "Szimpla Processzor", "item.refinedstorage.improved_processor": "Javított Processzor", "item.refinedstorage.advanced_processor": "Fejlett Processzor", "item.refinedstorage.1k_storage_part": "1k Tároló Rész", "item.refinedstorage.4k_storage_part": "4k Tároló Rész", "item.refinedstorage.16k_storage_part": "16k Tároló Rész", "item.refinedstorage.64k_storage_part": "64k Tároló Rész", "item.refinedstorage.64k_fluid_storage_part": "64k Folyadék Tároló Rész", "item.refinedstorage.256k_fluid_storage_part": "256k Folyadék Tároló Rész", "item.refinedstorage.1024k_fluid_storage_part": "1024k Folyadék Tároló Rész", "item.refinedstorage.4096k_fluid_storage_part": "4096k Folyadék Tároló Rész", "item.refinedstorage.pattern": "Sablon", "item.refinedstorage.upgrade": "Fejlesztés", "item.refinedstorage.range_upgrade": "Hatótáv Fejlesztés", "item.refinedstorage.speed_upgrade": "Sebesség Fejlesztés", "item.refinedstorage.crafting_upgrade": "Barkácsolás Fejlesztés", "item.refinedstorage.stack_upgrade": "Stack Fejlesztés", "item.refinedstorage.silk_touch_upgrade": "Gyengéd Érintés Fejlesztés", "item.refinedstorage.fortune_1_upgrade": "Szerencse Fejlesztés", "item.refinedstorage.fortune_2_upgrade": "Szerencse Fejlesztés", "item.refinedstorage.fortune_3_upgrade": "Szerencse Fejlesztés", "item.refinedstorage.regulator_upgrade": "Szabályozó Fejlesztés", "item.refinedstorage.storage_housing": "Tárhely Ház", "item.refinedstorage.filter": "Szűrő", "item.refinedstorage.network_card": "Hálózati Kártya", "item.refinedstorage.wrench": "Villáskulcs", "item.refinedstorage.security_card": "Biztonsági Kártya", "item.refinedstorage.security_card.owner": "%s-hoz kötve", "item.refinedstorage.processor_binding": "Processzor Kötés", "item.refinedstorage.cover": "Fedő", "item.refinedstorage.hollow_cover": "Üreges Fedő", "commands.refinedstorage.disk.create.error.disk_not_found": "%s lemez nem található.", "commands.refinedstorage.disk.create.success": "%s lemez sikeresen hozzáadva %s-hez.", "commands.refinedstorage.network.list.pos": "Hálózat X: %d, Y: %d, Z: %d koordinátákon", "commands.refinedstorage.network.list.tick_times": "Közelítőleges tick idő: %s ms. Közelítőleges TPS: %s", "commands.refinedstorage.network.list.autocrafting_tasks": "%s folyamatok", "commands.refinedstorage.network.list.nodes": "%s csomópontok", "commands.refinedstorage.network.list.energy_usage": "Energia felhasználás: %s", "commands.refinedstorage.network.get.error.not_found": "Hálózat nem található.", "commands.refinedstorage.network.autocrafting.get.error.not_found": "Folyamat nem található.", "commands.refinedstorage.network.autocrafting.cancel.single": "%d folyamat megszakítva.", "commands.refinedstorage.network.autocrafting.cancel.multiple": "%d folyamat megszakítva.", "advancements.refinedstorage.controlling.description": "Készíts egy Vezérlőt", "advancements.refinedstorage.connecting": "Csatlakozás", "advancements.refinedstorage.connecting.description": "Az összes eszközt egymás mellé teheted hogy csatlakozzanak, vagy használhatsz kábeleket", "advancements.refinedstorage.conditional_connecting": "Feltételes csatlakozás", "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", "advancements.refinedstorage.drives": "Meghajtók", "advancements.refinedstorage.drives.description": "Készíts egy Lemez meghajtót, hogy tárolni tudd a lemezeidet", "advancements.refinedstorage.manipulating_disks": "Lemezek kezelése", "advancements.refinedstorage.manipulating_disks.description": "Használj egy Lemez Kezelőt, hogy könnyen módosítsd egy lemez tartalmát", "advancements.refinedstorage.storing_items": "Tárgyak tárolása", "advancements.refinedstorage.storing_items.description": "Készíts egy Tároló Lemezt és tedd a Lemez Meghajtóba", "advancements.refinedstorage.viewing_items": "Tárgyak megnézése", "advancements.refinedstorage.viewing_items.description": "Készíts egy Rácsot, hogy használhasd a tárhelyedet", "advancements.refinedstorage.portable_storage": "Hordozható Tárhely", "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", "advancements.refinedstorage.upgrading_your_grid": "A Rácsod fejlesztése", "advancements.refinedstorage.upgrading_your_grid.description": "Fejleszd a Rácsodat egy Barkácsoló Ráccsá, hogy barkácsolhass a Rácsodban", "advancements.refinedstorage.storing_fluids": "Folyadékok tárolása", "advancements.refinedstorage.storing_fluids.description": "Készíts egy Folyadék Tároló Lemezt és tedd a Lemez Meghajtóba", "advancements.refinedstorage.viewing_fluids": "Folyadékok megnézése", "advancements.refinedstorage.viewing_fluids.description": "Készíts egy Folyadék Rácsot, hogy használhasd a folyadék tárhelyedet", "advancements.refinedstorage.better_than_a_barrel": "Jobb mint egy hordó", "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", "advancements.refinedstorage.autocrafting": "Autobarkácsolás", "advancements.refinedstorage.autocrafting.description": "Barkácsolj egy Barkácsolót", "advancements.refinedstorage.pattern_creation": "Sablon készítés", "advancements.refinedstorage.pattern_creation.description": "Készíts sablonokat egy Sablon Ráccsal és egy üres Sablonnal", "advancements.refinedstorage.monitoring": "Monitorozás", "advancements.refinedstorage.monitoring.description": "Nézd meg a barkácsoló folyamataid állapotát a Barkácsoló Monitorban", "advancements.refinedstorage.managing_patterns": "Sablonok kezelése", "advancements.refinedstorage.managing_patterns.description": "Készíts egy Barkácsoló Menedzsert, hogy egy jobb módon kezeld a sablonjaidat", "advancements.refinedstorage.importing": "Importálás", "advancements.refinedstorage.importing.description": "Tegyél tárgyakat vagy folyadékokat a tároló hálózatba egy Importálóval", "advancements.refinedstorage.destruction": "Megsemmisítés", "advancements.refinedstorage.destruction.description": "Tegyél tárgyakat vagy folyadékokat a tároló hálózatba egy Megsemmisítővel", "advancements.refinedstorage.exporting": "Exportálás", "advancements.refinedstorage.exporting.description": "Vegyél ki tárgyakat vagy folyadékokat a tároló hálózatból egy Exportálóval", "advancements.refinedstorage.construction": "Építés", "advancements.refinedstorage.construction.description": "Vegyél ki tárgyakat vagy folyadékokat a tároló hálózatból egy Építővel", "advancements.refinedstorage.security": "Biztonság", "advancements.refinedstorage.security.description": "Biztosítsd a hálózatodat egy Biztonsági Menedzserrel és egy Biztonsági Kártyával", "advancements.refinedstorage.wireless": "Vezeték Nélküli", "advancements.refinedstorage.wireless.description": "Továbbíts egy hálózati jelet egy Vezeték Nélküli Jeladóval", "advancements.refinedstorage.wireless_items": "Vezeték nélküli tárgyak", "advancements.refinedstorage.wireless_items.description": "Használd a tárolt tárgyaidat egy Vezeték Nélküli Ráccsal", "advancements.refinedstorage.wireless_fluids": "Vezeték nélküli folyadékok", "advancements.refinedstorage.wireless_fluids.description": "Használd a tárolt folyadékaidat egy Vezeték Nélküli Folyadék Ráccsal", "advancements.refinedstorage.wireless_monitoring": "Vezeték nélküli menedzselés", "advancements.refinedstorage.wireless_monitoring.description": "Nézd meg a barkácsoló folyamataid állapotát egy Vezeték Nélküli Barkácsolás Menedzserrel", "advancements.refinedstorage.no_cables_required": "Nincs szükség kábelekre", "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", "advancements.refinedstorage.upgrading": "Fejlesztés", "advancements.refinedstorage.upgrading.description": "Készíts egy Fejlesztést, hogy javíts az egyik eszközödön", "advancements.refinedstorage.crafting_on_demand": "Kérésre barkácsolás", "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", "advancements.refinedstorage.detecting": "Érzékelés", "advancements.refinedstorage.detecting.description": "Érzékelj Tárgyakat és Folyadékokat a hálózatban egy Érzékelővel", "advancements.refinedstorage.interface_to_the_world": "Interfész a világhoz", "advancements.refinedstorage.interface_to_the_world.description": "Exportálj és Importálj tárgyakat egyszerre egy Interfésszel", "advancements.refinedstorage.storing_externally": "Kívül tárolva", "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" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/it_it.json ================================================ { "itemGroup.refinedstorage": "Stoccaggio raffinato", "itemGroup.refinedstorage.covers": "Coperture di Stoccaggio raffinato", "key.refinedstorage.focusSearchBar": "Metti a fuoco la barra di ricerca della griglia", "key.refinedstorage.clearGridCraftingMatrix": "Pulisci la matrice di fabbricazione della griglia", "key.refinedstorage.openWirelessGrid": "Apri Griglia wireless", "key.refinedstorage.openWirelessFluidGrid": "Apri Griglia fluidi wireless", "key.refinedstorage.openPortableGrid": "Apri Griglia portatile", "key.refinedstorage.openWirelessCraftingMonitor": "Apri il monitor di fabbricazione wireless", "gui.refinedstorage.controller": "Regolatore", "gui.refinedstorage.creative_controller": "Regolatore creativo", "gui.refinedstorage.grid": "Griglia", "gui.refinedstorage.grid.craft": "Fabbrica", "gui.refinedstorage.crafting_grid": "Griglia di fabbricazione", "gui.refinedstorage.pattern_grid": "Griglia di modellazione", "gui.refinedstorage.grid.pattern_create": "Crea", "gui.refinedstorage.fluid_grid": "Griglia fluidi", "gui.refinedstorage.portable_grid": "Griglia portatile", "gui.refinedstorage.item_amount": "Quantità oggetto", "gui.refinedstorage.fluid_amount": "Quantità di fluido in mB", "gui.refinedstorage.disk_drive": "Unità disco", "gui.refinedstorage.disk_drive.disks": "Dischi", "gui.refinedstorage.disk_manipulator": "Manipolatore di dischi", "gui.refinedstorage.disk_manipulator.in": "In", "gui.refinedstorage.disk_manipulator.out": "Out", "gui.refinedstorage.external_storage": "Archiviazione esterna", "gui.refinedstorage.importer": "Importatore", "gui.refinedstorage.exporter": "Esportatore", "gui.refinedstorage.detector": "Rilevatore", "gui.refinedstorage.destructor": "Distruttore", "gui.refinedstorage.constructor": "Costruttore", "gui.refinedstorage.relay": "Relè", "gui.refinedstorage.interface.import": "Importazione interfaccia", "gui.refinedstorage.interface.export": "Esportazione interfaccia", "gui.refinedstorage.crafting_monitor": "Monitor di fabbricazione", "gui.refinedstorage.wireless_crafting_monitor": "Monitor di fabbricazione wireless", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d richiesto", "gui.refinedstorage.crafting_monitor.stored": "Immagazzinato: %d", "gui.refinedstorage.crafting_monitor.missing": "Mancante: %d", "gui.refinedstorage.crafting_monitor.processing": "Elaborazione: %d", "gui.refinedstorage.crafting_monitor.scheduled": "In programma: %d", "gui.refinedstorage.crafting_monitor.crafting": "Fabbricazione: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "La macchina non accetta l'oggetto", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "La macchina non accetta il fluido", "gui.refinedstorage.crafting_monitor.machine_none": "Nessuna macchina trovata", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Il fabbricatore è bloccato", "gui.refinedstorage.wireless_transmitter": "Trasmettitore wireless", "gui.refinedstorage.wireless_transmitter.distance": "%d blocco(i)", "gui.refinedstorage.crafter": "Fabbricatore", "gui.refinedstorage.filter": "Filtro", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Filtro mod", "gui.refinedstorage.network_transmitter": "Trasmettitore di rete", "gui.refinedstorage.network_transmitter.distance": "%d blocco(i)", "gui.refinedstorage.network_transmitter.missing_card": "Scheda di rete mancante", "gui.refinedstorage.fluid_interface": "Interfaccia fluidi", "gui.refinedstorage.fluid_interface.in": "In", "gui.refinedstorage.fluid_interface.out": "Out", "gui.refinedstorage.crafting_preview": "Anteprima della fabbricazione", "gui.refinedstorage.crafting_preview.to_craft": "Da fabbricare: %d", "gui.refinedstorage.crafting_preview.available": "Disponibile: %d", "gui.refinedstorage.crafting_preview.missing": "Mancante: %d", "gui.refinedstorage.crafting_preview.error": "Richiesta fallita", "gui.refinedstorage.crafting_preview.error.recursive.0": "Uno degli ingredienti della fabbricazione ha finito per aver bisogno di", "gui.refinedstorage.crafting_preview.error.recursive.1": "se stesso.", "gui.refinedstorage.crafting_preview.error.recursive.2": "È necessario rimuovere il modello o assicurarsi che", "gui.refinedstorage.crafting_preview.error.recursive.3": "il modello non viene utilizzato durante la fabbricazione.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Modello offensivo:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "Il calcolo dell'attività di fabbricazione era troppo complesso", "gui.refinedstorage.crafting_preview.error.too_complex.1": "ed è stato fermato per evitare lo sforzo del server.", "gui.refinedstorage.security_manager": "Responsabile della sicurezza", "gui.refinedstorage.security_manager.configure": "Configura", "gui.refinedstorage.security_manager.permission.0": "Inserisci", "gui.refinedstorage.security_manager.permission.0.tooltip": "Inserimento di oggetti o fluidi nella rete", "gui.refinedstorage.security_manager.permission.1": "Estrazione", "gui.refinedstorage.security_manager.permission.1.tooltip": "Estrai oggetti o fluidi dalla rete", "gui.refinedstorage.security_manager.permission.2": "Fabbricazione automatica", "gui.refinedstorage.security_manager.permission.2.tooltip": "Avviare, cancellare e visualizzare le attività di fabbricazione", "gui.refinedstorage.security_manager.permission.3": "Modifica", "gui.refinedstorage.security_manager.permission.3.tooltip": "Blocchi di apertura", "gui.refinedstorage.security_manager.permission.4": "Costruisci", "gui.refinedstorage.security_manager.permission.4.tooltip": "Aggiungi o rimuovi dispositivi alla o dalla rete", "gui.refinedstorage.security_manager.permission.5": "Sicurezza", "gui.refinedstorage.security_manager.permission.5.tooltip": "Possibilità di cambiare le opzioni di sicurezza", "gui.refinedstorage.storage_monitor": "Monitor di archiviazione", "gui.refinedstorage.crafter_manager": "Gestore dei fabbricatori", "gui.refinedstorage.alternatives": "Alternative", "gui.refinedstorage.alternatives.apply": "Applica", "gui.refinedstorage.jei.transfer.autocrafting_available": "Fabbricazione automatica disponibile", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRL + CLICK per richiedere la fabbricazione automatica", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMD + CLICK per richiedere la fabbricazione automatica", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Utilizzo: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Immagazzinato: %s", "misc.refinedstorage.storage.stored_capacity": "Immagazinato: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% pieno", "misc.refinedstorage.network_item.tooltip": "Collegato a %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Non c'è nessun trasmettitore wireless nel raggio d'azione.", "misc.refinedstorage.network_item.not_found": "Rete non trovata.", "misc.refinedstorage.network_item.shortcut_not_found": "Non c'è nessun %s nel tuo inventario.", "misc.refinedstorage.network_item.shortcut_duplicate": "C'è più di un %s nel tuo inventario.", "misc.refinedstorage.network_item.out_of_energy": "Il %s non ha più energia.", "misc.refinedstorage.network_card.tooltip": "Collegato a %d, %d, %d in %s.", "misc.refinedstorage.pattern.inputs": "Input", "misc.refinedstorage.pattern.outputs": "Output", "misc.refinedstorage.pattern.invalid": "Pattern non valido", "misc.refinedstorage.pattern.exact": "Utilizza la modalità esatta", "misc.refinedstorage.pattern.allowed_item_tag": "Utilizza oggetti da %s per %s", "misc.refinedstorage.pattern.allowed_fluid_tag": "Utilizza i fluidi da %s per %s", "misc.refinedstorage.pattern.error.processing_no_outputs": "Il modello di elaborazione non ha output", "misc.refinedstorage.pattern.error.no_output": "La ricetta non ha output", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "La ricetta non esiste", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "Il tag %s non è più applicabile per %s", "misc.refinedstorage.security.no_permission": "Non hai il permesso di eseguire quell'azione.", "misc.refinedstorage.start": "Avvia", "misc.refinedstorage.clear": "Azzera", "misc.refinedstorage.set": "Imposta", "misc.refinedstorage.cancel_all": "Annulla tutto", "misc.refinedstorage.priority": "Priorità", "misc.refinedstorage.exact": "Esatto", "misc.refinedstorage.processing": "Elaborazione", "misc.refinedstorage.total": "%s totale", "misc.refinedstorage.last_modified.just_now": "Ultima modifica di poco fa da %s", "misc.refinedstorage.last_modified.second": "Ultima modifica %d secondo fa da %s", "misc.refinedstorage.last_modified.seconds": "Ultima modifica %d secondi fa da %s", "misc.refinedstorage.last_modified.minute": "Ultima modifica %d minuto fa da %s", "misc.refinedstorage.last_modified.minutes": "Ultima modifica %d minuti fa da %s", "misc.refinedstorage.last_modified.hour": "Ultima modifica %d ora fa da %s", "misc.refinedstorage.last_modified.hours": "Ultima modifica %d ore fa da %s", "misc.refinedstorage.last_modified.day": "Ultima modifica %d giorno fa da %s", "misc.refinedstorage.last_modified.days": "Ultima modifica %d giorni fa da %s", "misc.refinedstorage.last_modified.week": "Ultima modifica %d settimana fa da %s", "misc.refinedstorage.last_modified.weeks": "Ultima modifica %d settimane fa da %s", "misc.refinedstorage.last_modified.year": "Ultima modifica %d anno fa da %s", "misc.refinedstorage.last_modified.years": "Ultima modifica %d anni fa da %s", "sidebutton.refinedstorage.exact_mode": "Modalità esatta", "sidebutton.refinedstorage.exact_mode.on": "On", "sidebutton.refinedstorage.exact_mode.off": "Off", "sidebutton.refinedstorage.redstone_mode": "Modalità di Redstone", "sidebutton.refinedstorage.redstone_mode.0": "Ignora segnale di redstone", "sidebutton.refinedstorage.redstone_mode.1": "Funziona solo con un segnale di redstone", "sidebutton.refinedstorage.redstone_mode.2": "Funziona solo senza un segnale di redstone", "sidebutton.refinedstorage.crafter_mode": "Modalità Fabbricatore", "sidebutton.refinedstorage.crafter_mode.0": "Ignora segnale di redstone", "sidebutton.refinedstorage.crafter_mode.1": "Il segnale di redstone sblocca la fabbricazione automatica", "sidebutton.refinedstorage.crafter_mode.2": "Il segnale di redstone blocca la fabbricazione automatica", "sidebutton.refinedstorage.crafter_mode.3": "L'impulso di redstone inserisce il prossimo set", "sidebutton.refinedstorage.grid.view_type": "Visualizzazione", "sidebutton.refinedstorage.grid.view_type.0": "Normale", "sidebutton.refinedstorage.grid.view_type.1": "Nessuno fabbricabile", "sidebutton.refinedstorage.grid.view_type.2": "Solo i fabbricabili", "sidebutton.refinedstorage.grid.sorting.direction": "Direzione di ordinamento", "sidebutton.refinedstorage.grid.sorting.direction.0": "Crescente", "sidebutton.refinedstorage.grid.sorting.direction.1": "Decrescente", "sidebutton.refinedstorage.grid.sorting.type": "Tipo di ordinamento", "sidebutton.refinedstorage.grid.sorting.type.0": "Quantità", "sidebutton.refinedstorage.grid.sorting.type.1": "Nome", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Ultima modifica", "sidebutton.refinedstorage.grid.search_box_mode": "Modalità casella di ricerca", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normale", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normale (autoselezionato)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Sincronizzato con JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Sincronizzato con JEI (autoselezionato)", "sidebutton.refinedstorage.grid.search_box_mode.4": "Sincronizzato con JEI (bidirezionale)", "sidebutton.refinedstorage.grid.search_box_mode.5": "Sincronizzato con JEI (autoselezione bidirezionale)", "sidebutton.refinedstorage.grid.size": "Dimensione", "sidebutton.refinedstorage.grid.size.0": "Allungato", "sidebutton.refinedstorage.grid.size.1": "Piccolo", "sidebutton.refinedstorage.grid.size.2": "Medio", "sidebutton.refinedstorage.grid.size.3": "Grande", "sidebutton.refinedstorage.mode": "Modalità", "sidebutton.refinedstorage.mode.whitelist": "Lista bianca", "sidebutton.refinedstorage.mode.blacklist": "Lista nera", "sidebutton.refinedstorage.iomode": "Modalità IO", "sidebutton.refinedstorage.iomode.insert": "Inserire nella rete", "sidebutton.refinedstorage.iomode.extract": "Estrai dalla rete", "sidebutton.refinedstorage.type": "Tipo", "sidebutton.refinedstorage.type.0": "Oggetti", "sidebutton.refinedstorage.type.1": "Fluidi", "sidebutton.refinedstorage.detector.mode": "Modalità", "sidebutton.refinedstorage.detector.mode.0": "Emetti il segnale quando è inferiore alla quantità", "sidebutton.refinedstorage.detector.mode.1": "Emetti il segnale quando si arriva alla quantità", "sidebutton.refinedstorage.detector.mode.2": "Emetti il segnale quando si supera la quantità", "sidebutton.refinedstorage.constructor.drop": "Rilascia i blocchi invece di posizionarli", "sidebutton.refinedstorage.destructor.pickup": "Raccogli oggetti invece di romperli", "sidebutton.refinedstorage.access_type": "Tipo di accesso", "sidebutton.refinedstorage.access_type.0": "Inserisci ed estrai", "sidebutton.refinedstorage.access_type.1": "Inserisci solo", "sidebutton.refinedstorage.access_type.2": "Estrai solo", "block.refinedstorage.controller": "Regolatore", "block.refinedstorage.creative_controller": "Regolatore creativo", "block.refinedstorage.cable": "Cavo", "block.refinedstorage.grid": "Griglia", "block.refinedstorage.crafting_grid": "Griglia di fabbricazione", "block.refinedstorage.pattern_grid": "Griglia di modellazione", "block.refinedstorage.fluid_grid": "Griglia fluidi", "block.refinedstorage.disk_drive": "Unità disco", "block.refinedstorage.disk_manipulator": "Manipolatore di dischi", "block.refinedstorage.external_storage": "Archiviazione esterna", "block.refinedstorage.importer": "Importatore", "block.refinedstorage.exporter": "Esportatore", "block.refinedstorage.detector": "Rilevatore", "block.refinedstorage.machine_casing": "Involucro della macchina", "block.refinedstorage.destructor": "Distruttore", "block.refinedstorage.constructor": "Costruttore", "block.refinedstorage.1k_storage_block": "Blocco di memoria da 1k", "block.refinedstorage.4k_storage_block": "Blocco di memoria da 4k", "block.refinedstorage.16k_storage_block": "Blocco di memoria da 16k", "block.refinedstorage.64k_storage_block": "Blocco di memoria da 64k", "block.refinedstorage.creative_storage_block": "Blocco di memoria creativo", "block.refinedstorage.relay": "Relè", "block.refinedstorage.interface": "Interfaccia", "block.refinedstorage.crafting_monitor": "Monitor di fabbricazione", "block.refinedstorage.wireless_transmitter": "Trasmettitore wireless", "block.refinedstorage.crafter": "Fabbricatore", "block.refinedstorage.network_receiver": "Ricevitore di rete", "block.refinedstorage.network_transmitter": "Trasmettitore di rete", "block.refinedstorage.fluid_interface": "Interfaccia fluidi", "block.refinedstorage.64k_fluid_storage_block": "Blocco di memoria fluida da 64k", "block.refinedstorage.256k_fluid_storage_block": "Blocco di memoria fluida da 256k", "block.refinedstorage.1024k_fluid_storage_block": "Blocco di memoria fluida da 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Blocco di memoria fluida da 4096k", "block.refinedstorage.creative_fluid_storage_block": "Blocco di memoria fluida creativa", "block.refinedstorage.security_manager": "Responsabile della sicurezza", "block.refinedstorage.quartz_enriched_iron_block": "Blocco di ferro arricchito di quarzo", "block.refinedstorage.storage_monitor": "Monitor di archiviazione", "block.refinedstorage.portable_grid": "Griglia portatile", "block.refinedstorage.creative_portable_grid": "Griglia portatile creativa", "block.refinedstorage.portable_grid.tooltip": "Accovacciati per posizionare nel mondo.", "block.refinedstorage.crafter_manager": "Gestore dei fabbricatori", "item.refinedstorage.1k_storage_disk": "Disco di archiviazione da 1k", "item.refinedstorage.4k_storage_disk": "Disco di archiviazione 4k", "item.refinedstorage.16k_storage_disk": "Disco di archiviazione da 16k", "item.refinedstorage.64k_storage_disk": "Disco di archiviazione da 64k", "item.refinedstorage.creative_storage_disk": "Disco di archiviazione creativo", "item.refinedstorage.64k_fluid_storage_disk": "Disco di archiviazione fluido da 64k", "item.refinedstorage.256k_fluid_storage_disk": "Disco di archiviazione fluido da 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Disco di archiviazione fluido da 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Disco di archiviazione fluido da 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Disco di archiviazione fluido creativo", "item.refinedstorage.wireless_grid": "Griglia wireless", "item.refinedstorage.creative_wireless_grid": "Griglia wireless creativa", "item.refinedstorage.wireless_fluid_grid": "Griglia fluida wireless", "item.refinedstorage.creative_wireless_fluid_grid": "Griglia fluida wireless creativa", "item.refinedstorage.wireless_crafting_monitor": "Monitor di fabbricazione wireless", "item.refinedstorage.creative_wireless_crafting_monitor": "Monitor fabbricazione wireless creativo", "item.refinedstorage.quartz_enriched_iron": "Ferro arricchito di quarzo", "item.refinedstorage.construction_core": "Nucleo di costruzione", "item.refinedstorage.destruction_core": "Nucleo di distruzione", "item.refinedstorage.silicon": "Silicio", "item.refinedstorage.raw_basic_processor": "Processore di base grezzo", "item.refinedstorage.raw_improved_processor": "Processore migliorato grezzo", "item.refinedstorage.raw_advanced_processor": "Processore avanzato grezzo", "item.refinedstorage.basic_processor": "Processore di base", "item.refinedstorage.improved_processor": "Processore migliorato", "item.refinedstorage.advanced_processor": "Processore avanzato", "item.refinedstorage.1k_storage_part": "Parte di archiviazione da 1k", "item.refinedstorage.4k_storage_part": "Parte di archiviazione da 4k", "item.refinedstorage.16k_storage_part": "Parte di archiviazione da 16k", "item.refinedstorage.64k_storage_part": "Parte di archiviazione da 64k", "item.refinedstorage.64k_fluid_storage_part": "Parte di archiviazione fluida da 64k", "item.refinedstorage.256k_fluid_storage_part": "Parte di archiviazione fluida da 256k", "item.refinedstorage.1024k_fluid_storage_part": "Parte di archiviazione fluida da 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Parte di archiviazione fluida da 4096k", "item.refinedstorage.pattern": "Modello", "item.refinedstorage.upgrade": "Potenziamento", "item.refinedstorage.range_upgrade": "Potenziamento raggio", "item.refinedstorage.speed_upgrade": "Potenziamento velocità", "item.refinedstorage.crafting_upgrade": "Potenziamento fabbricazione", "item.refinedstorage.stack_upgrade": "Potenziamento stack", "item.refinedstorage.silk_touch_upgrade": "Potenziamento Tocco di velluto", "item.refinedstorage.fortune_1_upgrade": "Potenziamento Fortuna", "item.refinedstorage.fortune_2_upgrade": "Potenziamento Fortuna", "item.refinedstorage.fortune_3_upgrade": "Potenziamento Fortuna", "item.refinedstorage.regulator_upgrade": "Potenziamento regolatore", "item.refinedstorage.storage_housing": "Custodia di archiviazione", "item.refinedstorage.filter": "Filtro", "item.refinedstorage.network_card": "Scheda di rete", "item.refinedstorage.wrench": "Chiave inglese", "item.refinedstorage.security_card": "Scheda di sicurezza", "item.refinedstorage.security_card.owner": "Associato a: %s", "item.refinedstorage.processor_binding": "Legatura del processore", "commands.refinedstorage.disk.create.error.disk_not_found": "Il disco %s non è stato trovato.", "commands.refinedstorage.disk.create.success": "Dato con successo il disco %s a %s.", "commands.refinedstorage.network.list.pos": "Rete a X: %d, Y: %d, Z: %d", "commands.refinedstorage.network.list.tick_times": "Tempo medio di tick: %s ms. TPS medio: %s", "commands.refinedstorage.network.list.autocrafting_tasks": "%s attività", "commands.refinedstorage.network.list.nodes": "%s nodi", "commands.refinedstorage.network.list.energy_usage": "Consumo energetico: %s", "commands.refinedstorage.network.get.error.not_found": "Rete non trovata.", "commands.refinedstorage.network.autocrafting.get.error.not_found": "Attività non trovata.", "commands.refinedstorage.network.autocrafting.cancel.single": "Attività %d annullata.", "commands.refinedstorage.network.autocrafting.cancel.multiple": "%d attività annullate.", "advancements.refinedstorage.controlling.description": "Fabbrica un regolatore", "advancements.refinedstorage.connecting": "Connessione in corso", "advancements.refinedstorage.connecting.description": "Si possono mettere tutti i dispositivi uno accanto all'altro per collegarli, oppure, utilizzare dei Cavi", "advancements.refinedstorage.conditional_connecting": "Collegamento condizionale", "advancements.refinedstorage.conditional_connecting.description": "Fabbrica un relè per controllare se un segnale di rete può passare con la redstone", "advancements.refinedstorage.drives": "Unità", "advancements.refinedstorage.drives.description": "Fabbrica un'unità disco per poter conservare i tuoi dischi", "advancements.refinedstorage.manipulating_disks": "Manipolazione dei dischi", "advancements.refinedstorage.manipulating_disks.description": "Utilizza un manipolatore di dischi per modificare facilmente il contenuto dei dischi", "advancements.refinedstorage.storing_items": "Archiviazione di oggetti", "advancements.refinedstorage.storing_items.description": "Crea un disco di archiviazione e mettilo nell'unità disco", "advancements.refinedstorage.viewing_items": "Visualizzazione degli oggetti", "advancements.refinedstorage.viewing_items.description": "Fabbrica una griglia per interagire con lo spazio di archiviazione degli oggetti", "advancements.refinedstorage.portable_storage": "Archiviazione portatile", "advancements.refinedstorage.portable_storage.description": "Fabbrica una Griglia portatile per accedere a oggetti e fluidi nei dischi senza essere in una rete", "advancements.refinedstorage.upgrading_your_grid": "Potenziamento della tua Griglia", "advancements.refinedstorage.upgrading_your_grid.description": "Potenzia la tua griglia in una Griglia di fabbricazione per ottenere abilità di fabbricazione nella tua griglia", "advancements.refinedstorage.storing_fluids": "Archiviazione dei fluidi", "advancements.refinedstorage.storing_fluids.description": "Crea un disco di archiviazione fluido e mettilo nell'unità disco", "advancements.refinedstorage.viewing_fluids": "Visualizzazione dei fluidi", "advancements.refinedstorage.viewing_fluids.description": "Fabbrica una Griglia fluida per interagire con lo spazio di archiviazione degli oggetti", "advancements.refinedstorage.better_than_a_barrel": "Meglio di un barile", "advancements.refinedstorage.better_than_a_barrel.description": "Fabbrica un Monitor di archiviazione per visualizzare, inserire o estrarre elementi di una rete", "advancements.refinedstorage.autocrafting": "Fabbricazione automatica", "advancements.refinedstorage.autocrafting.description": "Fabbrica un Fabbricatore", "advancements.refinedstorage.pattern_creation": "Creazione di modello", "advancements.refinedstorage.pattern_creation.description": "Fabbrica modelli con una Griglia di modellazione e un Modello", "advancements.refinedstorage.monitoring": "Controllo", "advancements.refinedstorage.monitoring.description": "Controlla lo stato delle tue attività di fabbricazione con il Monitor di Fabbricazione", "advancements.refinedstorage.managing_patterns": "Gestione dei modelli", "advancements.refinedstorage.managing_patterns.description": "Fabbrica un Gestore dei fabbricatori per gestire meglio i tuoi modelli", "advancements.refinedstorage.importing": "Importazione in corso", "advancements.refinedstorage.importing.description": "Introduci oggetti o fluidi nella rete di archiviazione con un Importatore", "advancements.refinedstorage.destruction": "Distruzione", "advancements.refinedstorage.destruction.description": "Introduci blocchi o fluidi nella rete di archiviazione con un Distruttore", "advancements.refinedstorage.exporting": "Esportazione in corso", "advancements.refinedstorage.exporting.description": "Estrai oggetti o fluidi dalla rete di archiviazione con un Esportatore", "advancements.refinedstorage.construction": "Costruzione", "advancements.refinedstorage.construction.description": "Estrai blocchi o fluidi dalla rete di archiviazione con un Costruttore", "advancements.refinedstorage.security": "Sicurezza", "advancements.refinedstorage.security.description": "Proteggi la tua rete con un Responsabile della sicurezza e una Scheda di sicurezza", "advancements.refinedstorage.wireless": "Wireless", "advancements.refinedstorage.wireless.description": "Trasmetti un segnale di rete con un Trasmettitore wireless", "advancements.refinedstorage.wireless_items": "Oggetti wireless", "advancements.refinedstorage.wireless_items.description": "Interagisci con lo spazio di archiviazione degli oggetti in modalità wireless con una Griglia wireless", "advancements.refinedstorage.wireless_fluids": "Fluidi wireless", "advancements.refinedstorage.wireless_fluids.description": "Interagisci con lo spazio di archiviazione di fluidi in modalità wireless con una Griglia fluidi wireless", "advancements.refinedstorage.wireless_monitoring": "Monitoraggio wireless", "advancements.refinedstorage.wireless_monitoring.description": "Controlla lo stato delle tue attività di fabbricazione in modalità wireless con il Monitor di fabbricazione wireless", "advancements.refinedstorage.no_cables_required": "Nessun cavo richiesto", "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", "advancements.refinedstorage.upgrading": "Potenziamento", "advancements.refinedstorage.upgrading.description": "Fabbrica un potenziamento per migliorare vari dispositivi", "advancements.refinedstorage.crafting_on_demand": "Fabbricazione su richiesta", "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", "advancements.refinedstorage.detecting": "Rilevamento", "advancements.refinedstorage.detecting.description": "Rileva oggetti o fluidi nella rete con il rilevatore", "advancements.refinedstorage.interface_to_the_world": "Interfaccia con il mondo", "advancements.refinedstorage.interface_to_the_world.description": "Esporta e importa oggetti allo stesso tempo con un'interfaccia", "advancements.refinedstorage.storing_externally": "Conservazione esterna", "advancements.refinedstorage.storing_externally.description": "Utilizza un'Archiviazione esterna per fornire alla rete l'archiviazione da un blocco esterno come un baule" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/ja_jp.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage カバー", "key.refinedstorage.focusSearchBar": "グリッドの検索欄を選択", "key.refinedstorage.clearGridCraftingMatrix": "グリッドのクラフト欄をクリア", "key.refinedstorage.openWirelessGrid": "ワイヤレスグリッドを開く", "key.refinedstorage.openWirelessFluidGrid": "ワイヤレス流体グリッドを開く", "key.refinedstorage.openPortableGrid": "携帯グリッドを開く", "key.refinedstorage.openWirelessCraftingMonitor": "ワイヤレスクラフトモニターを開く", "gui.refinedstorage.controller": "コントローラー", "gui.refinedstorage.creative_controller": "クリエイティブコントローラー", "gui.refinedstorage.grid": "グリッド", "gui.refinedstorage.grid.craft": "クラフト", "gui.refinedstorage.crafting_grid": "製作グリッド", "gui.refinedstorage.pattern_grid": "パターングリッド", "gui.refinedstorage.grid.pattern_create": "作成", "gui.refinedstorage.fluid_grid": "流体グリッド", "gui.refinedstorage.portable_grid": "携帯グリッド", "gui.refinedstorage.item_amount": "アイテムの量", "gui.refinedstorage.fluid_amount": "流体の量 (mB)", "gui.refinedstorage.disk_drive": "ディスクドライブ", "gui.refinedstorage.disk_drive.disks": "ディスク", "gui.refinedstorage.disk_manipulator": "ディスクマニピュレーター", "gui.refinedstorage.disk_manipulator.in": "搬入", "gui.refinedstorage.disk_manipulator.out": "搬出", "gui.refinedstorage.external_storage": "拡張ストレージ", "gui.refinedstorage.importer": "インポーター", "gui.refinedstorage.exporter": "エクスポーター", "gui.refinedstorage.detector": "ディテクター", "gui.refinedstorage.destructor": "デストラクター", "gui.refinedstorage.constructor": "コンストラクター", "gui.refinedstorage.relay": "リレー", "gui.refinedstorage.interface.import": "インターフェース:搬入", "gui.refinedstorage.interface.export": "インターフェース:搬出", "gui.refinedstorage.crafting_monitor": "クラフトモニター", "gui.refinedstorage.wireless_crafting_monitor": "ワイヤレスクラフトモニター", "gui.refinedstorage.crafting_monitor.tooltip.requested": "要求数 %d", "gui.refinedstorage.crafting_monitor.stored": "在庫: %d", "gui.refinedstorage.crafting_monitor.missing": "不足: %d", "gui.refinedstorage.crafting_monitor.processing": "加工中: %d", "gui.refinedstorage.crafting_monitor.scheduled": "加工予定: %d", "gui.refinedstorage.crafting_monitor.crafting": "クラフト中: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "機械にアイテムを搬入できません", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "機械に流体を搬入できません", "gui.refinedstorage.crafting_monitor.machine_none": "機械が見つかりません", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "クラフターがロックされています", "gui.refinedstorage.wireless_transmitter": "ワイヤレス送信機", "gui.refinedstorage.wireless_transmitter.distance": "%dブロック", "gui.refinedstorage.crafter": "クラフター", "gui.refinedstorage.filter": "フィルター", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Modフィルター", "gui.refinedstorage.network_transmitter": "ネットワーク送信機", "gui.refinedstorage.network_transmitter.distance": "%dブロック", "gui.refinedstorage.network_transmitter.missing_card": "ネットワークカードが見つかりません", "gui.refinedstorage.fluid_interface": "流体インターフェース", "gui.refinedstorage.fluid_interface.in": "搬入", "gui.refinedstorage.fluid_interface.out": "搬出", "gui.refinedstorage.crafting_preview": "クラフトのプレビュー", "gui.refinedstorage.crafting_preview.to_craft": "作成数: %d", "gui.refinedstorage.crafting_preview.available": "使用: %d", "gui.refinedstorage.crafting_preview.missing": "不足: %d", "gui.refinedstorage.crafting_preview.error": "リクエストに失敗しました", "gui.refinedstorage.crafting_preview.error.recursive.0": "材料が自身を要求しています", "gui.refinedstorage.crafting_preview.error.recursive.1": "該当パターンの削除", "gui.refinedstorage.crafting_preview.error.recursive.2": "または", "gui.refinedstorage.crafting_preview.error.recursive.3": "クラフト中に使われていないことを確認する必要があります", "gui.refinedstorage.crafting_preview.error.recursive.4": "該当パターン:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "クラフト過程の計算が複雑すぎます", "gui.refinedstorage.crafting_preview.error.too_complex.1": "サーバーの負担を避けるため計算が停止されました", "gui.refinedstorage.security_manager": "セキュリティマネージャー", "gui.refinedstorage.security_manager.configure": "設定", "gui.refinedstorage.security_manager.permission.0": "搬入", "gui.refinedstorage.security_manager.permission.0.tooltip": "アイテムをネットワークに搬入する", "gui.refinedstorage.security_manager.permission.1": "搬出", "gui.refinedstorage.security_manager.permission.1.tooltip": "アイテムをネットワークから搬出する", "gui.refinedstorage.security_manager.permission.2": "自動クラフト", "gui.refinedstorage.security_manager.permission.2.tooltip": "自動クラフトの開始・キャンセルやクラフト過程の確認", "gui.refinedstorage.security_manager.permission.3": "変更", "gui.refinedstorage.security_manager.permission.3.tooltip": "ブロックのGUIを開く", "gui.refinedstorage.security_manager.permission.4": "構築", "gui.refinedstorage.security_manager.permission.4.tooltip": "ネットワークのデバイスを追加または撤去する", "gui.refinedstorage.security_manager.permission.5": "セキュリティ", "gui.refinedstorage.security_manager.permission.5.tooltip": "セキュリティ設定を変更する権限", "gui.refinedstorage.storage_monitor": "ストレージモニター", "gui.refinedstorage.crafter_manager": "クラフターマネージャー", "gui.refinedstorage.alternatives": "代替案", "gui.refinedstorage.alternatives.apply": "適用", "gui.refinedstorage.jei.transfer.autocrafting_available": "自動クラフトが出来る", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRLキーを押しながらクリックするために自動クラフトする", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMDキーを押しながらクリックするために自動クラフトする", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "消費電力: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "在庫: %s", "misc.refinedstorage.storage.stored_capacity": "在庫: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%%を使用中", "misc.refinedstorage.network_item.tooltip": "%d, %d, %dにリンク済", "misc.refinedstorage.network_item.out_of_range": "有効範囲内のワイヤレス送信機がありません", "misc.refinedstorage.network_item.not_found": "ネットワークが見つかりません", "misc.refinedstorage.network_item.shortcut_not_found": "インベントリに%sがありません", "misc.refinedstorage.network_item.shortcut_duplicate": "インベントリに%sが複数あります", "misc.refinedstorage.network_item.out_of_energy": "%sがエネルギー切れです", "misc.refinedstorage.network_card.tooltip": "%sの%d, %d, %dにリンク済", "misc.refinedstorage.pattern.inputs": "材料", "misc.refinedstorage.pattern.outputs": "完成品", "misc.refinedstorage.pattern.invalid": "無効なパターン", "misc.refinedstorage.pattern.exact": "精密モードを使用", "misc.refinedstorage.pattern.allowed_item_tag": "%sに%sのアイテムを使用する", "misc.refinedstorage.pattern.allowed_fluid_tag": "%sに%sの流体を使用する", "misc.refinedstorage.pattern.error.processing_no_outputs": "加工中のパターンに完成品がありません", "misc.refinedstorage.pattern.error.no_output": "指定されたレシピに完成品がありません", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "指定されたレシピは存在しません", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "タグ %s は%sに適用できなくなりました", "misc.refinedstorage.security.no_permission": "その行動をする権限がありません", "misc.refinedstorage.start": "開始", "misc.refinedstorage.clear": "クリア", "misc.refinedstorage.set": "完了", "misc.refinedstorage.cancel_all": "全てキャンセル", "misc.refinedstorage.priority": "優先度", "misc.refinedstorage.exact": "精密モード", "misc.refinedstorage.processing": "加工", "misc.refinedstorage.total": "%s個", "misc.refinedstorage.last_modified.just_now": "%sが直前に変更", "misc.refinedstorage.last_modified.second": "%dが%s秒前に変更", "misc.refinedstorage.last_modified.seconds": "%dが%s秒前に変更", "misc.refinedstorage.last_modified.minute": "%dが%s分前に変更", "misc.refinedstorage.last_modified.minutes": "%dが%s分前に変更", "misc.refinedstorage.last_modified.hour": "%dが%s時間前に変更", "misc.refinedstorage.last_modified.hours": "%dが%s時間前に変更", "misc.refinedstorage.last_modified.day": "%dが%s日前に変更", "misc.refinedstorage.last_modified.days": "%dが%s日前に変更", "misc.refinedstorage.last_modified.week": "%dが%s週間前に変更", "misc.refinedstorage.last_modified.weeks": "%dが%s週間前に変更", "misc.refinedstorage.last_modified.year": "%dが%s年前に変更", "misc.refinedstorage.last_modified.years": "%dが%s年前に変更", "sidebutton.refinedstorage.exact_mode": "精密モード", "sidebutton.refinedstorage.exact_mode.on": "オン", "sidebutton.refinedstorage.exact_mode.off": "オフ", "sidebutton.refinedstorage.redstone_mode": "レッドストーン", "sidebutton.refinedstorage.redstone_mode.0": "レッドストーン信号を無視", "sidebutton.refinedstorage.redstone_mode.1": "レッドストーン入力時のみ動作", "sidebutton.refinedstorage.redstone_mode.2": "レッドストーン入力がない時のみ動作", "sidebutton.refinedstorage.crafter_mode": "動作モード", "sidebutton.refinedstorage.crafter_mode.0": "レッドストーン信号を無視", "sidebutton.refinedstorage.crafter_mode.1": "レッドストーン信号で自動クラフトのロック解除", "sidebutton.refinedstorage.crafter_mode.2": "レッドストーン信号で自動クラフトをロック", "sidebutton.refinedstorage.crafter_mode.3": "レッドストーンパルスで次セットを搬入", "sidebutton.refinedstorage.grid.view_type": "表示", "sidebutton.refinedstorage.grid.view_type.0": "通常", "sidebutton.refinedstorage.grid.view_type.1": "クラフト不可能な物のみ表示", "sidebutton.refinedstorage.grid.view_type.2": "クラフト可能な物のみ表示", "sidebutton.refinedstorage.grid.sorting.direction": "並び順", "sidebutton.refinedstorage.grid.sorting.direction.0": "昇順", "sidebutton.refinedstorage.grid.sorting.direction.1": "降順", "sidebutton.refinedstorage.grid.sorting.type": "並べ替え", "sidebutton.refinedstorage.grid.sorting.type.0": "量", "sidebutton.refinedstorage.grid.sorting.type.1": "名前", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "最終変更時間", "sidebutton.refinedstorage.grid.search_box_mode": "検索ボックス", "sidebutton.refinedstorage.grid.search_box_mode.0": "通常", "sidebutton.refinedstorage.grid.search_box_mode.1": "通常 (自動選択)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEIと連動", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEIと連動 (自動選択)", "sidebutton.refinedstorage.grid.size": "サイズ", "sidebutton.refinedstorage.grid.size.0": "画面サイズと連動", "sidebutton.refinedstorage.grid.size.1": "小", "sidebutton.refinedstorage.grid.size.2": "中", "sidebutton.refinedstorage.grid.size.3": "大", "sidebutton.refinedstorage.mode": "モード", "sidebutton.refinedstorage.mode.whitelist": "ホワイトリスト", "sidebutton.refinedstorage.mode.blacklist": "ブラックリスト", "sidebutton.refinedstorage.iomode": "搬入出", "sidebutton.refinedstorage.iomode.insert": "ネットワークへ搬出", "sidebutton.refinedstorage.iomode.extract": "ネットワークから搬入", "sidebutton.refinedstorage.type": "種類", "sidebutton.refinedstorage.type.0": "アイテム", "sidebutton.refinedstorage.type.1": "流体", "sidebutton.refinedstorage.detector.mode": "モード", "sidebutton.refinedstorage.detector.mode.0": "指定数を下回ると信号出力", "sidebutton.refinedstorage.detector.mode.1": "指定数で信号出力", "sidebutton.refinedstorage.detector.mode.2": "指定数を上回ると信号出力", "sidebutton.refinedstorage.constructor.drop": "ブロックを設置せずにアイテム化させる", "sidebutton.refinedstorage.destructor.pickup": "ブロックを破壊せずにアイテムを拾う", "sidebutton.refinedstorage.access_type": "アクセスの種類", "sidebutton.refinedstorage.access_type.0": "搬入・搬出", "sidebutton.refinedstorage.access_type.1": "搬入のみ", "sidebutton.refinedstorage.access_type.2": "搬出のみ", "block.refinedstorage.controller": "コントローラー", "block.refinedstorage.creative_controller": "クリエイティブコントローラー", "block.refinedstorage.cable": "ケーブル", "block.refinedstorage.grid": "グリッド", "block.refinedstorage.crafting_grid": "製作グリッド", "block.refinedstorage.pattern_grid": "パターングリッド", "block.refinedstorage.fluid_grid": "流体グリッド", "block.refinedstorage.disk_drive": "ディスクドライブ", "block.refinedstorage.disk_manipulator": "ディスクマニピュレーター", "block.refinedstorage.external_storage": "外部ストレージ", "block.refinedstorage.importer": "インポーター", "block.refinedstorage.exporter": "エクスポーター", "block.refinedstorage.detector": "検出器", "block.refinedstorage.machine_casing": "マシンケーシング", "block.refinedstorage.destructor": "ディストラクター", "block.refinedstorage.constructor": "コンストラクター", "block.refinedstorage.1k_storage_block": "1千ストレージブロック", "block.refinedstorage.4k_storage_block": "4千ストレージブロック", "block.refinedstorage.16k_storage_block": "16千ストレージブロック", "block.refinedstorage.64k_storage_block": "64千ストレージブロック", "block.refinedstorage.creative_storage_block": "クリエイティブストレージブロック", "block.refinedstorage.relay": "リレー", "block.refinedstorage.interface": "インターフェース", "block.refinedstorage.crafting_monitor": "クラフトモニター", "block.refinedstorage.wireless_transmitter": "ワイヤレス送信機", "block.refinedstorage.wireless_transmitter.tooltip": "%sの上に設置する必要があります", "block.refinedstorage.crafter": "クラフター", "block.refinedstorage.network_receiver": "ネットワーク受信機", "block.refinedstorage.network_transmitter": "ネットワーク送信機", "block.refinedstorage.fluid_interface": "流体インターフェース", "block.refinedstorage.64k_fluid_storage_block": "64千流体ストレージブロック", "block.refinedstorage.256k_fluid_storage_block": "256千流体ストレージブロック", "block.refinedstorage.1024k_fluid_storage_block": "1024千流体ストレージブロック", "block.refinedstorage.4096k_fluid_storage_block": "4096千流体ストレージブロック", "block.refinedstorage.creative_fluid_storage_block": "クリエイティブ流体ストレージブロック", "block.refinedstorage.security_manager": "セキュリティマネージャー", "block.refinedstorage.quartz_enriched_iron_block": "クォーツ濃縮鉄ブロック", "block.refinedstorage.storage_monitor": "ストレージモニター", "block.refinedstorage.portable_grid": "携帯グリッド", "block.refinedstorage.creative_portable_grid": "クリエイティブ携帯グリッド", "block.refinedstorage.portable_grid.tooltip": "スニークで設置可能", "block.refinedstorage.crafter_manager": "クラフターマネージャー", "item.refinedstorage.1k_storage_disk": "1千ストレージディスク", "item.refinedstorage.4k_storage_disk": "4千ストレージディスク", "item.refinedstorage.16k_storage_disk": "16千ストレージディスク", "item.refinedstorage.64k_storage_disk": "64千ストレージディスク", "item.refinedstorage.creative_storage_disk": "クリエイティブストレージディスク", "item.refinedstorage.64k_fluid_storage_disk": "64千流体ストレージディスク", "item.refinedstorage.256k_fluid_storage_disk": "256千流体ストレージディスク", "item.refinedstorage.1024k_fluid_storage_disk": "1024千流体ストレージディスク", "item.refinedstorage.4096k_fluid_storage_disk": "4096千流体ストレージディスク", "item.refinedstorage.creative_fluid_storage_disk": "クリエイティブ流体ストレージディスク", "item.refinedstorage.wireless_grid": "ワイヤレスグリッド", "item.refinedstorage.creative_wireless_grid": "クリエイティブワイヤレスグリッド", "item.refinedstorage.wireless_fluid_grid": "ワイヤレス流体グリッド", "item.refinedstorage.creative_wireless_fluid_grid": "クリエイティブワイヤレス流体グリッド", "item.refinedstorage.wireless_crafting_monitor": "ワイヤレスクラフトモニター", "item.refinedstorage.creative_wireless_crafting_monitor": "クリエイティブワイヤレスクラフトモニター", "item.refinedstorage.quartz_enriched_iron": "クォーツ濃縮鉄", "item.refinedstorage.construction_core": "コンストラクションコア", "item.refinedstorage.destruction_core": "デストラクションコア", "item.refinedstorage.silicon": "シリコン", "item.refinedstorage.raw_basic_processor": "生の基本プロセッサ", "item.refinedstorage.raw_improved_processor": "生の改良プロセッサ", "item.refinedstorage.raw_advanced_processor": "生の発展プロセッサ", "item.refinedstorage.basic_processor": "基本プロセッサ", "item.refinedstorage.improved_processor": "改良プロセッサ", "item.refinedstorage.advanced_processor": "発展プロセッサ", "item.refinedstorage.1k_storage_part": "1千ストレージパーツ", "item.refinedstorage.4k_storage_part": "4千ストレージパーツ", "item.refinedstorage.16k_storage_part": "16千ストレージパーツ", "item.refinedstorage.64k_storage_part": "64千ストレージパーツ", "item.refinedstorage.64k_fluid_storage_part": "64千流体ストレージパーツ", "item.refinedstorage.256k_fluid_storage_part": "256千流体ストレージパーツ", "item.refinedstorage.1024k_fluid_storage_part": "1024千流体ストレージパーツ", "item.refinedstorage.4096k_fluid_storage_part": "4096千流体ストレージパーツ", "item.refinedstorage.pattern": "パターン", "item.refinedstorage.upgrade": "アップグレード", "item.refinedstorage.range_upgrade": "レンジアップグレード", "item.refinedstorage.speed_upgrade": "スピードアップグレード", "item.refinedstorage.crafting_upgrade": "クラフティングアップグレード", "item.refinedstorage.stack_upgrade": "スタックアップグレード", "item.refinedstorage.silk_touch_upgrade": "シルクタッチアップグレード", "item.refinedstorage.fortune_1_upgrade": "幸運アップグレード", "item.refinedstorage.fortune_2_upgrade": "幸運アップグレード", "item.refinedstorage.fortune_3_upgrade": "幸運アップグレード", "item.refinedstorage.regulator_upgrade": "レギュレータアップグレード", "item.refinedstorage.storage_housing": "ストレージハウジング", "item.refinedstorage.filter": "フィルター", "item.refinedstorage.network_card": "ネットワークカード", "item.refinedstorage.wrench": "レンチ", "item.refinedstorage.security_card": "セキュリティカード", "item.refinedstorage.security_card.owner": "所有者: %s", "item.refinedstorage.processor_binding": "プロセッサ接合材", "commands.refinedstorage.disk.create.error.disk_not_found": "ディスク%sが見つかりません", "commands.refinedstorage.disk.create.success": "ディスク%sを%sに割り当てました", "advancements.refinedstorage.controlling.description": "コントローラーを作る", "advancements.refinedstorage.connecting": "接続", "advancements.refinedstorage.connecting.description": "装置を隣接させて設置する他、ケーブルを使用することもできます", "advancements.refinedstorage.conditional_connecting": "条件付きの接続", "advancements.refinedstorage.conditional_connecting.description": "ネットワーク信号をレッドストーンで接続・遮断するリレーを作る", "advancements.refinedstorage.drives": "ドライブ", "advancements.refinedstorage.drives.description": "ディスクの保管を可能にするディスクドライブを作る", "advancements.refinedstorage.manipulating_disks": "ディスク操作", "advancements.refinedstorage.manipulating_disks.description": "ディスクマニピュレータを使用してディスクの中身を簡単に変更する", "advancements.refinedstorage.storing_items": "アイテムを貯蔵", "advancements.refinedstorage.storing_items.description": "ストレージディスクを作成してディスクドライブに搭載する", "advancements.refinedstorage.viewing_items": "アイテムを確認", "advancements.refinedstorage.viewing_items.description": "グリッドを作成してアイテムのストレージにアクセスする", "advancements.refinedstorage.portable_storage": "携帯ストレージ", "advancements.refinedstorage.portable_storage.description": "ネットワーク内でなくてもディスク内のアイテムや流体にアクセスできる携帯グリッドを作る", "advancements.refinedstorage.upgrading_your_grid": "グリッドのアップグレード", "advancements.refinedstorage.upgrading_your_grid.description": "グリッドを製作グリッドにアップグレードするとクラフトが可能になります", "advancements.refinedstorage.storing_fluids": "流体を貯蔵", "advancements.refinedstorage.storing_fluids.description": "流体ストレージディスクを作成してディスクドライブに搭載する", "advancements.refinedstorage.viewing_fluids": "流体を確認", "advancements.refinedstorage.viewing_fluids.description": "流体グリッドを作成して流体ストレージにアクセスする", "advancements.refinedstorage.better_than_a_barrel": "バレルよりも良い", "advancements.refinedstorage.better_than_a_barrel.description": "ネットワーク内のアイテムを表示し、搬入出を行うストレージモニターを作る", "advancements.refinedstorage.autocrafting": "自動クラフト", "advancements.refinedstorage.autocrafting.description": "クラフターを作る", "advancements.refinedstorage.pattern_creation": "パターンを作成", "advancements.refinedstorage.pattern_creation.description": "パターングリッドとパターンを使用してパターンを作る", "advancements.refinedstorage.monitoring": "モニタリング", "advancements.refinedstorage.monitoring.description": "クラフトモニターを使用して自動クラフトの状況をチェックする", "advancements.refinedstorage.managing_patterns": "パターンの管理", "advancements.refinedstorage.managing_patterns.description": "クラフターマネージャーを使用してより良い方法でパターンを管理する", "advancements.refinedstorage.importing": "搬入", "advancements.refinedstorage.importing.description": "インポーターを使用してアイテムや流体をストレージネットワークに取り込む", "advancements.refinedstorage.destruction": "破壊", "advancements.refinedstorage.destruction.description": "デストラクターを使用してアイテムや流体をストレージネットワークに取り込む", "advancements.refinedstorage.exporting": "搬出", "advancements.refinedstorage.exporting.description": "エクスポーターを使用してネットワークからブロックや流体を取り出す", "advancements.refinedstorage.construction": "構築", "advancements.refinedstorage.construction.description": "コンストラクターを使用してネットワークからブロックや流体を取り出す", "advancements.refinedstorage.security": "セキュリティ", "advancements.refinedstorage.security.description": "セキュリティマネージャーとセキュリティカードを使用してあなたのネットワークを保護する", "advancements.refinedstorage.wireless": "ワイヤレス", "advancements.refinedstorage.wireless.description": "ワイヤレス送信機を使用してネットワーク信号を送出する", "advancements.refinedstorage.wireless_items": "ワイヤレスアイテム", "advancements.refinedstorage.wireless_items.description": "ワイヤレスグリッドを使用してワイヤレスでアイテムのストレージにアクセスする", "advancements.refinedstorage.wireless_fluids": "ワイヤレス流体", "advancements.refinedstorage.wireless_fluids.description": "ワイヤレス流体グリッドを使用してワイヤレスで流体ストレージにアクセスする", "advancements.refinedstorage.wireless_monitoring": "ワイヤレスモニタリング", "advancements.refinedstorage.wireless_monitoring.description": "ワイヤレスクラフトモニターを使用して自動クラフトの状況をワイヤレスでチェックする", "advancements.refinedstorage.no_cables_required": "ケーブル不要", "advancements.refinedstorage.no_cables_required.description": "ネットワーク送信機と受信機、ネットワークカードを使用してケーブルを使用せずにネットワークに装置を追加する", "advancements.refinedstorage.upgrading": "アップグレード", "advancements.refinedstorage.upgrading.description": "様々な装置を改善するアップグレードを作る", "advancements.refinedstorage.crafting_on_demand": "クラフティング・オンデマンド", "advancements.refinedstorage.crafting_on_demand.description": "インターフェースやエクスポーター、コンストラクターにクラフティングアップグレードを搭載してアイテムやブロックをオンデマンドで作る", "advancements.refinedstorage.detecting": "検知", "advancements.refinedstorage.detecting.description": "検出器を使用してネットワーク内のアイテムや流体を検出する", "advancements.refinedstorage.interface_to_the_world": "世界への接点", "advancements.refinedstorage.interface_to_the_world.description": "インターフェースでアイテムの搬入出を同時に行う", "advancements.refinedstorage.storing_externally": "外部保管", "advancements.refinedstorage.storing_externally.description": "拡張ストレージを利用してチェストのような外部のブロックからネットワークにストレージを供給する" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/ko_kr.json ================================================ { "itemGroup.refinedstorage": "리파인드 스토리지", "itemGroup.refinedstorage.covers": "리파인드 스토리지 커버즈", "key.refinedstorage.focusSearchBar": "그리드 검색", "key.refinedstorage.clearGridCraftingMatrix": "그리드 제작 매트릭스 지우기", "key.refinedstorage.openWirelessGrid": "무선 그리드 열기", "key.refinedstorage.openWirelessFluidGrid": "무선 액체 그리드 열기", "key.refinedstorage.openPortableGrid": "휴대용 그리드 열기", "key.refinedstorage.openWirelessCraftingMonitor": "무선 제작 모니터 열기", "gui.refinedstorage.controller": "콘트롤러", "gui.refinedstorage.creative_controller": "크리에이티브 콘트롤러", "gui.refinedstorage.grid": "그리드", "gui.refinedstorage.grid.craft": "제작", "gui.refinedstorage.crafting_grid": "제작 그리드", "gui.refinedstorage.pattern_grid": "패턴 그리드", "gui.refinedstorage.grid.pattern_create": "패턴 제작", "gui.refinedstorage.fluid_grid": "액체 그리드", "gui.refinedstorage.portable_grid": "휴대용 그리드", "gui.refinedstorage.item_amount": "아이템 양", "gui.refinedstorage.fluid_amount": "액량(mB)", "gui.refinedstorage.disk_drive": "디스크 드라이브", "gui.refinedstorage.disk_drive.disks": "디스크", "gui.refinedstorage.disk_manipulator": "디스크 조작기", "gui.refinedstorage.disk_manipulator.in": "입력", "gui.refinedstorage.disk_manipulator.out": "출력", "gui.refinedstorage.external_storage": "외부 저장공간", "gui.refinedstorage.importer": "입력기", "gui.refinedstorage.exporter": "출력기", "gui.refinedstorage.detector": "감지기", "gui.refinedstorage.destructor": "파괴기", "gui.refinedstorage.constructor": "설치기", "gui.refinedstorage.relay": "중계기", "gui.refinedstorage.interface.import": "인터페이스 입력", "gui.refinedstorage.interface.export": "인터페이스 출력", "gui.refinedstorage.crafting_monitor": "제작 모니터", "gui.refinedstorage.wireless_crafting_monitor": "무선 제작 모니터", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d 요청됨", "gui.refinedstorage.crafting_monitor.stored": "저장: %d", "gui.refinedstorage.crafting_monitor.missing": "부족: %d", "gui.refinedstorage.crafting_monitor.processing": "처리: %d", "gui.refinedstorage.crafting_monitor.scheduled": "예정: %d", "gui.refinedstorage.crafting_monitor.crafting": "제작: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "기계가 아이템을 허용하지 않습니다.", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "기계가 액체를 허용하지 않습니다.", "gui.refinedstorage.crafting_monitor.machine_none": "기계를 찾을 수 없습니다.", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "제작기가 잠겼습니다.", "gui.refinedstorage.wireless_transmitter": "무선 송신기", "gui.refinedstorage.wireless_transmitter.distance": "%d블럭", "gui.refinedstorage.crafter": "제작기", "gui.refinedstorage.filter": "필터", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "모드 필터", "gui.refinedstorage.network_transmitter": "네트워크 송신기", "gui.refinedstorage.network_transmitter.distance": "%d블럭", "gui.refinedstorage.network_transmitter.missing_card": "부족한 네트워크 카드", "gui.refinedstorage.fluid_interface": "액체 인터페이스", "gui.refinedstorage.fluid_interface.in": "입력", "gui.refinedstorage.fluid_interface.out": "출력", "gui.refinedstorage.crafting_preview": "제작 미리보기", "gui.refinedstorage.crafting_preview.to_craft": "제작할 아이템: %d", "gui.refinedstorage.crafting_preview.available": "사용 가능: %d", "gui.refinedstorage.crafting_preview.missing": "부족: %d", "gui.refinedstorage.crafting_preview.error": "요청에 실패했습니다.", "gui.refinedstorage.crafting_preview.error.recursive.0": "제작 재료 중 하나는 결국 ", "gui.refinedstorage.crafting_preview.error.recursive.1": "스스로가 필요하게 되었습니다.", "gui.refinedstorage.crafting_preview.error.recursive.2": "패턴을 제거하거나 제작 시 ", "gui.refinedstorage.crafting_preview.error.recursive.3": "패턴이 사용되지 않도록 해야 합니다.", "gui.refinedstorage.crafting_preview.error.recursive.4": "불쾌감을 주는 패턴:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "제작 작업 계산이 너무 복잡하여 ", "gui.refinedstorage.crafting_preview.error.too_complex.1": "서버 부담을 피하기 위해 중지되었습니다.", "gui.refinedstorage.security_manager": "보안 관리자", "gui.refinedstorage.security_manager.configure": "설정", "gui.refinedstorage.security_manager.permission.0": "삽입", "gui.refinedstorage.security_manager.permission.0.tooltip": "네트워크에 아이템이나 액체를 삽입하기", "gui.refinedstorage.security_manager.permission.1": "추출", "gui.refinedstorage.security_manager.permission.1.tooltip": "네트워크에서 아이템이나 액체를 추출하기", "gui.refinedstorage.security_manager.permission.2": "자동 제작하기", "gui.refinedstorage.security_manager.permission.2.tooltip": "자동 제작 시작, 중지 및 현재 작업 보기", "gui.refinedstorage.security_manager.permission.3": "수정", "gui.refinedstorage.security_manager.permission.3.tooltip": "네트워크 상의 GUI 열기", "gui.refinedstorage.security_manager.permission.4": "조작", "gui.refinedstorage.security_manager.permission.4.tooltip": "네트워크에 장치를 추가하거나 제거하기", "gui.refinedstorage.security_manager.permission.5": "보안", "gui.refinedstorage.security_manager.permission.5.tooltip": "보안 옵션 조정하기", "gui.refinedstorage.storage_monitor": "저장 모니터", "gui.refinedstorage.crafter_manager": "제작기 관리자", "gui.refinedstorage.alternatives": "대체", "gui.refinedstorage.alternatives.apply": "적용", "gui.refinedstorage.jei.transfer.autocrafting_available": "자동 제작 사용 가능", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRL + 클릭하여 자동 제작 요청", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMD + 클릭하여 자동 제작 요청", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "사용: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "저장량: %s", "misc.refinedstorage.storage.stored_capacity": "저쟝량: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% 가득 참", "misc.refinedstorage.network_item.tooltip": "%d, %d, %d로 연결됨", "misc.refinedstorage.network_item.out_of_range": "근방에 무선 송신기가 없습니다.", "misc.refinedstorage.network_item.not_found": "콘트롤러를 찾을 수 없습니다.", "misc.refinedstorage.network_item.shortcut_not_found": "인벤토리에 %s이(가) 없습니다.", "misc.refinedstorage.network_item.shortcut_duplicate": "인벤토리에 두 개 이상의 %s이(가) 있습니다.", "misc.refinedstorage.network_item.out_of_energy": "%s의 에너지가 부족합니다.", "misc.refinedstorage.network_card.tooltip": "%d, %d, %d로 연결됨", "misc.refinedstorage.pattern.inputs": "입력", "misc.refinedstorage.pattern.outputs": "출력", "misc.refinedstorage.pattern.invalid": "잘못된 패턴", "misc.refinedstorage.pattern.exact": "정확한 모드 사용", "misc.refinedstorage.pattern.allowed_item_tag": "%s에 대해 %s의 아이템을 사용합니다.", "misc.refinedstorage.pattern.allowed_fluid_tag": "%s에 대해 %s의 액체를 사용합니다.", "misc.refinedstorage.pattern.error.processing_no_outputs": "처리 패턴에 출력이 없습니다.", "misc.refinedstorage.pattern.error.no_output": "제작법에 출력이 없습니다.", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "제작법이 존재하지 않습니다.", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "%s 태그를 %s에 더 이상 적용할 수 없습니다.", "misc.refinedstorage.security.no_permission": "해당 작업을 실행할 권한이 없습니다.", "misc.refinedstorage.start": "시작", "misc.refinedstorage.clear": "초기화", "misc.refinedstorage.set": "설정", "misc.refinedstorage.cancel_all": "모두 취소", "misc.refinedstorage.priority": "우선 순위", "misc.refinedstorage.exact": "정확성", "misc.refinedstorage.processing": "처리", "misc.refinedstorage.fluidmode": "액체", "misc.refinedstorage.total": "%s 합계", "misc.refinedstorage.last_modified.just_now": "%s에 의해 방금 전에 최종 수정됨", "misc.refinedstorage.last_modified.second": "%s초 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.seconds": "%s초 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.minute": "%s분 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.minutes": "%s분 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.hour": "%s시간 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.hours": "%s시간 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.day": "%s일 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.days": "%s일 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.week": "%s주 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.weeks": "%s주 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.year": "%s년 전 %d에 의해 마지막으로 수정됨", "misc.refinedstorage.last_modified.years": "%s년 전 %d에 의해 마지막으로 수정됨", "sidebutton.refinedstorage.exact_mode": "정확한 모드", "sidebutton.refinedstorage.exact_mode.on": "켜짐", "sidebutton.refinedstorage.exact_mode.off": "꺼짐", "sidebutton.refinedstorage.redstone_mode": "레드스톤 모드", "sidebutton.refinedstorage.redstone_mode.0": "신호와 상관 없이 작동", "sidebutton.refinedstorage.redstone_mode.1": "신호를 받을 때 작동", "sidebutton.refinedstorage.redstone_mode.2": "신호를 받지 않을 때 작동", "sidebutton.refinedstorage.crafter_mode": "제작기 모드", "sidebutton.refinedstorage.crafter_mode.0": "레드스톤 신호 무시", "sidebutton.refinedstorage.crafter_mode.1": "레드스톤 신호가 자동 제작의 잠금을 해제합니다.", "sidebutton.refinedstorage.crafter_mode.2": "레드스톤 신호가 자동 제작을 잠급니다.", "sidebutton.refinedstorage.crafter_mode.3": "레드스톤 펄스가 다음 세트를 삽입합니다.", "sidebutton.refinedstorage.grid.view_type": "표시", "sidebutton.refinedstorage.grid.view_type.0": "일반", "sidebutton.refinedstorage.grid.view_type.1": "제작 가능 아이템 숨김", "sidebutton.refinedstorage.grid.view_type.2": "제작 가능 아이템만 표시", "sidebutton.refinedstorage.grid.sorting.direction": "정렬", "sidebutton.refinedstorage.grid.sorting.direction.0": "오름차순", "sidebutton.refinedstorage.grid.sorting.direction.1": "내림차순", "sidebutton.refinedstorage.grid.sorting.type": "정렬 기준", "sidebutton.refinedstorage.grid.sorting.type.0": "수량", "sidebutton.refinedstorage.grid.sorting.type.1": "이름", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "인벤토리트윅스", "sidebutton.refinedstorage.grid.sorting.type.4": "최근 수정", "sidebutton.refinedstorage.grid.search_box_mode": "검색 모드", "sidebutton.refinedstorage.grid.search_box_mode.0": "일반", "sidebutton.refinedstorage.grid.search_box_mode.1": "일반 (자동 선택됨)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI 통합", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI 통합 (자동 선택됨)", "sidebutton.refinedstorage.grid.search_box_mode.4": "JEI 통합 (양방향)", "sidebutton.refinedstorage.grid.search_box_mode.5": "JEI 통합 (양방향 자동 선택됨)", "sidebutton.refinedstorage.grid.size": "크기", "sidebutton.refinedstorage.grid.size.0": "맞춤", "sidebutton.refinedstorage.grid.size.1": "작음", "sidebutton.refinedstorage.grid.size.2": "중간", "sidebutton.refinedstorage.grid.size.3": "큼", "sidebutton.refinedstorage.mode": "모드", "sidebutton.refinedstorage.mode.whitelist": "화이트리스트", "sidebutton.refinedstorage.mode.blacklist": "블랙리스트", "sidebutton.refinedstorage.iomode": "입출력 모드", "sidebutton.refinedstorage.iomode.insert": "네트워크로 입력", "sidebutton.refinedstorage.iomode.extract": "네트워크에서 출력", "sidebutton.refinedstorage.type": "종류", "sidebutton.refinedstorage.type.0": "아이템", "sidebutton.refinedstorage.type.1": "액체", "sidebutton.refinedstorage.detector.mode": "모드", "sidebutton.refinedstorage.detector.mode.0": "수량 이하일 때 신호 출력", "sidebutton.refinedstorage.detector.mode.1": "수량과 일치할 때 신호 출력", "sidebutton.refinedstorage.detector.mode.2": "수량 이상일 때 신호 출력", "sidebutton.refinedstorage.constructor.drop": "블럭을 설치하지 않고 떨어트림", "sidebutton.refinedstorage.destructor.pickup": "블럭을 파괴하지 않고 주움", "sidebutton.refinedstorage.access_type": "액세스 종류", "sidebutton.refinedstorage.access_type.0": "입출력", "sidebutton.refinedstorage.access_type.1": "입력", "sidebutton.refinedstorage.access_type.2": "출력", "block.refinedstorage.controller": "콘트롤러", "block.refinedstorage.creative_controller": "크리에이티브 콘트롤러", "block.refinedstorage.cable": "케이블", "block.refinedstorage.grid": "그리드", "block.refinedstorage.crafting_grid": "제작 그리드", "block.refinedstorage.pattern_grid": "패턴 그리드", "block.refinedstorage.fluid_grid": "액체 그리드", "block.refinedstorage.disk_drive": "디스크 드라이브", "block.refinedstorage.disk_manipulator": "디스크 조작기", "block.refinedstorage.external_storage": "외부 저장공간", "block.refinedstorage.importer": "입력기", "block.refinedstorage.exporter": "출력기", "block.refinedstorage.detector": "감지기", "block.refinedstorage.machine_casing": "기계 케이싱", "block.refinedstorage.destructor": "파괴기", "block.refinedstorage.constructor": "설치기", "block.refinedstorage.1k_storage_block": "1k 저장공간", "block.refinedstorage.4k_storage_block": "4k 저장공간", "block.refinedstorage.16k_storage_block": "16k 저장공간", "block.refinedstorage.64k_storage_block": "64k 저장공간", "block.refinedstorage.creative_storage_block": "크리에이티브 저장공간", "block.refinedstorage.relay": "중계기", "block.refinedstorage.interface": "인터페이스", "block.refinedstorage.crafting_monitor": "제작 모니터", "block.refinedstorage.wireless_transmitter": "무선 송신기", "block.refinedstorage.crafter": "제작기", "block.refinedstorage.network_receiver": "네트워크 수신기", "block.refinedstorage.network_transmitter": "네트워크 송신기", "block.refinedstorage.fluid_interface": "액체 인터페이스", "block.refinedstorage.64k_fluid_storage_block": "64k 액체 저장공간", "block.refinedstorage.256k_fluid_storage_block": "256k 액체 저장공간", "block.refinedstorage.1024k_fluid_storage_block": "1024k 액체 저장공간", "block.refinedstorage.4096k_fluid_storage_block": "4096k 액체 저장공간", "block.refinedstorage.creative_fluid_storage_block": "크리에이티브 액체 저장공간", "block.refinedstorage.security_manager": "보안 관리자", "block.refinedstorage.quartz_enriched_iron_block": "석영 강화 철 블럭", "block.refinedstorage.storage_monitor": "저장 모니터", "block.refinedstorage.portable_grid": "휴대용 그리드", "block.refinedstorage.creative_portable_grid": "크리에이티브 휴대용 그리드", "block.refinedstorage.portable_grid.tooltip": "웅크리기로 설치할 수 있습니다.", "block.refinedstorage.crafter_manager": "제작기 관리자", "item.refinedstorage.1k_storage_disk": "1k 저장 디스크", "item.refinedstorage.4k_storage_disk": "4k 저장 디스크", "item.refinedstorage.16k_storage_disk": "16k 저장 디스크", "item.refinedstorage.64k_storage_disk": "64k 저장 디스크", "item.refinedstorage.creative_storage_disk": "크리에이티브 저장 디스크", "item.refinedstorage.64k_fluid_storage_disk": "64k 액체 저장 디스크", "item.refinedstorage.256k_fluid_storage_disk": "256k 액체 저장 디스크", "item.refinedstorage.1024k_fluid_storage_disk": "1024k 액체 저장 디스크", "item.refinedstorage.4096k_fluid_storage_disk": "4096k 액체 저장 디스크", "item.refinedstorage.creative_fluid_storage_disk": "크리에이티브 액체 저장 디스크", "item.refinedstorage.wireless_grid": "무선 그리드", "item.refinedstorage.creative_wireless_grid": "크리에이티브 무선 그리드", "item.refinedstorage.wireless_fluid_grid": "무선 액체 그리드", "item.refinedstorage.creative_wireless_fluid_grid": "크리에이티브 무선 액체 그리드", "item.refinedstorage.wireless_crafting_monitor": "무선 제작 모니터", "item.refinedstorage.creative_wireless_crafting_monitor": "크리에이티브 무선 제작 모니터", "item.refinedstorage.quartz_enriched_iron": "석영 강화 철", "item.refinedstorage.construction_core": "형성 코어", "item.refinedstorage.destruction_core": "파괴 코어", "item.refinedstorage.silicon": "실리콘", "item.refinedstorage.raw_basic_processor": "처리되지 않은 기본 프로세서", "item.refinedstorage.raw_improved_processor": "처리되지 않은 강화 프로세서", "item.refinedstorage.raw_advanced_processor": "처리되지 않은 고급 프로세서", "item.refinedstorage.basic_processor": "기본 프로세서", "item.refinedstorage.improved_processor": "강화 프로세서", "item.refinedstorage.advanced_processor": "고급 프로세서", "item.refinedstorage.1k_storage_part": "1k 저장 파트", "item.refinedstorage.4k_storage_part": "4k 저장 파트", "item.refinedstorage.16k_storage_part": "16k 저장 파트", "item.refinedstorage.64k_storage_part": "64k 저장 파트", "item.refinedstorage.64k_fluid_storage_part": "64k 액체 저장 파트", "item.refinedstorage.256k_fluid_storage_part": "256k 액체 저장 파트", "item.refinedstorage.1024k_fluid_storage_part": "1024k 액체 저장 파트", "item.refinedstorage.4096k_fluid_storage_part": "4096k 액체 저장 파트", "item.refinedstorage.pattern": "패턴", "item.refinedstorage.upgrade": "업그레이드", "item.refinedstorage.range_upgrade": "범위 업그레이드", "item.refinedstorage.speed_upgrade": "속도 업그레이드", "item.refinedstorage.crafting_upgrade": "제작 업그레이드", "item.refinedstorage.stack_upgrade": "세트 업그레이드", "item.refinedstorage.silk_touch_upgrade": "섬세한 손길 업그레이드", "item.refinedstorage.fortune_1_upgrade": "행운 업그레이드", "item.refinedstorage.fortune_2_upgrade": "행운 업그레이드", "item.refinedstorage.fortune_3_upgrade": "행운 업그레이드", "item.refinedstorage.regulator_upgrade": "조절기 업그레이드", "item.refinedstorage.storage_housing": "저장공간 하우징", "item.refinedstorage.filter": "필터", "item.refinedstorage.network_card": "네트워크 카드", "item.refinedstorage.wrench": "렌치", "item.refinedstorage.security_card": "보안 카드", "item.refinedstorage.security_card.owner": "플레이어: %s", "item.refinedstorage.processor_binding": "프로세서 바인딩", "item.refinedstorage.cover": "커버", "item.refinedstorage.hollow_cover": "빈 커버", "commands.refinedstorage.disk.create.error.disk_not_found": "%s 디스크를 찾을 수 없습니다.", "commands.refinedstorage.disk.create.success": "%s 디스크에 %s을(를) 부여했습니다.", "commands.refinedstorage.network.list.pos": "X: %d, Y: %d, Z: %d에서의 네트워크", "commands.refinedstorage.network.list.tick_times": "평균 틱 시간: %s ms. 평균 TPS: %s", "commands.refinedstorage.network.list.autocrafting_tasks": "%s 작업", "commands.refinedstorage.network.list.nodes": "%s 노드", "commands.refinedstorage.network.list.energy_usage": "에너지 사용: %s", "commands.refinedstorage.network.get.error.not_found": "네트워크를 찾지 못했습니다.", "commands.refinedstorage.network.autocrafting.get.error.not_found": "작업를 찾지 못했습니다.", "commands.refinedstorage.network.autocrafting.cancel.single": "작업 %d개를 취소했습니다.", "commands.refinedstorage.network.autocrafting.cancel.multiple": "작업 %d개를 취소했습니다.", "advancements.refinedstorage.controlling.description": "콘트롤러를 제작합니다.", "advancements.refinedstorage.connecting": "연결", "advancements.refinedstorage.connecting.description": "모든 장치를 나란히 배치하여 연결하거나 케이블을 사용할 수 있습니다.", "advancements.refinedstorage.conditional_connecting": "조건부 연결", "advancements.refinedstorage.conditional_connecting.description": "네트워크 신호가 레드스톤으로 전달될 수 있는지 제어하기 위해 중계기를 제작합니다.", "advancements.refinedstorage.drives": "드라이브", "advancements.refinedstorage.drives.description": "디스크를 저장할 수 있도록 디스크 드라이브를 제작합니다.", "advancements.refinedstorage.manipulating_disks": "디스크 조작", "advancements.refinedstorage.manipulating_disks.description": "디스크 조작기를 사용하여 디스크 내용을 쉽게 수정합니다.", "advancements.refinedstorage.storing_items": "아이템 정렬", "advancements.refinedstorage.storing_items.description": "저장 디스크를 제작하여 디스크 드라이브에 넣습니다.", "advancements.refinedstorage.viewing_items": "아이템 보기", "advancements.refinedstorage.viewing_items.description": "그리드를 제작하여 아이템 저장공간과 상호 작용합니다.", "advancements.refinedstorage.portable_storage": "휴대용 저장공간", "advancements.refinedstorage.portable_storage.description": "휴대용 그리드를 제작하여 네트워크에 있지 않고 디스크의 아이템 및 액체에 접근할 수 있습니다.", "advancements.refinedstorage.upgrading_your_grid": "그리드를 업그레이드하기", "advancements.refinedstorage.upgrading_your_grid.description": "그리드를 제작 그리드로 업그레이드하여 그리드에서 제작 기능을 얻으십시오.", "advancements.refinedstorage.storing_fluids": "액체 저장", "advancements.refinedstorage.storing_fluids.description": "액체 저장 디스크를 제작하여 디스크 드라이브에 넣습니다.", "advancements.refinedstorage.viewing_fluids": "액체 보기", "advancements.refinedstorage.viewing_fluids.description": "액체 저장공간과 상호 작용하도록 액체 그리드를 제작합니다.", "advancements.refinedstorage.better_than_a_barrel": "통보다 좋다!", "advancements.refinedstorage.better_than_a_barrel.description": "저장 모니터를 제작하여 네트워크의 아이템을 보거나 삽입 또는 추출합니다.", "advancements.refinedstorage.autocrafting": "자동 제작", "advancements.refinedstorage.autocrafting.description": "제작기를 제작합니다.", "advancements.refinedstorage.pattern_creation": "패턴 제작", "advancements.refinedstorage.pattern_creation.description": "패턴 그리드 및 패턴을 사용하여 패턴을 작성합니다.", "advancements.refinedstorage.monitoring": "감시", "advancements.refinedstorage.monitoring.description": "제작 모니터로 제작 작업의 상태를 확인합니다.", "advancements.refinedstorage.managing_patterns": "패턴 관리", "advancements.refinedstorage.managing_patterns.description": "제작기 관리자를 제작하여 패턴을 보다 효율적으로 관리할 수 있습니다.", "advancements.refinedstorage.importing": "입력", "advancements.refinedstorage.importing.description": "입력기를 사용하여 아이템 또는 액체를 저장공간 네트워크로 가져옵니다.", "advancements.refinedstorage.destruction": "파괴", "advancements.refinedstorage.destruction.description": "파괴기를 사용하여 블록이나 액체를 저장공간 네트워크로 가져옵니다.", "advancements.refinedstorage.exporting": "출력", "advancements.refinedstorage.exporting.description": "출력기를 사용하여 블록이나 액체를 저장공간 네트워크로 가져옵니다.", "advancements.refinedstorage.construction": "설치", "advancements.refinedstorage.construction.description": "설치기를 사용하여 저장공간 네트워크에서 블록이나 액체를 얻습니다.", "advancements.refinedstorage.security": "보안", "advancements.refinedstorage.security.description": "보안 관리자 및 보안 카드를 사용하여 네트워크를 보호하십시오.", "advancements.refinedstorage.wireless": "무선", "advancements.refinedstorage.wireless.description": "무선 송신기로 네트워크 신호를 전송합니다.", "advancements.refinedstorage.wireless_items": "무선 아이템", "advancements.refinedstorage.wireless_items.description": "무선 그리드를 통해 아이템 저장공간과 무선으로 상호작용하십시오.", "advancements.refinedstorage.wireless_fluids": "무선 액체", "advancements.refinedstorage.wireless_fluids.description": "무선 액체 그리드로 액체 저장공간과 무선으로 상호작용하십시오.", "advancements.refinedstorage.wireless_monitoring": "무선 감시", "advancements.refinedstorage.wireless_monitoring.description": "무선 제작 모니터로 무선으로 제작 작업의 상태를 확인하십시오.", "advancements.refinedstorage.no_cables_required": "케이블을 요구하지 않습니다.", "advancements.refinedstorage.no_cables_required.description": "네트워크 송신기, 네트워크 수신기 및 네트워크 카드를 사용하여 케이블을 사용하지 않고도 네트워크에 추가 구성요소를 추가할 수 있습니다.", "advancements.refinedstorage.upgrading": "업그레이드", "advancements.refinedstorage.upgrading.description": "다양한 장치를 개선하기 위해 업그레이드를 제작합니다.", "advancements.refinedstorage.crafting_on_demand": "주문형 제작", "advancements.refinedstorage.crafting_on_demand.description": "인터페이스, 출력기 또는 설치기에서 제작 업그레이드를 사용하여 주문형 아이템 및 블록을 제작합니다.", "advancements.refinedstorage.detecting": "탐지", "advancements.refinedstorage.detecting.description": "감지기를 사용하여 네트워크의 아이템 또는 액체를 탐지합니다.", "advancements.refinedstorage.interface_to_the_world": "월드에 대한 인터페이스", "advancements.refinedstorage.interface_to_the_world.description": "인터페이스로 아이템을 동시에 내보내고 가져옵니다.", "advancements.refinedstorage.storing_externally": "외부로 저장", "advancements.refinedstorage.storing_externally.description": "외부 저장공간을 사용하여 네트워크에 상자와 같은 외부 블록의 저장공간을 제공합니다." } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/nl_nl.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "gui.refinedstorage.controller": "Controller", "gui.refinedstorage.creative_controller": "Creative Controller", "gui.refinedstorage.grid": "Rooster", "gui.refinedstorage.grid.craft": "Craft", "gui.refinedstorage.grid.pattern_create": "Patroon maken", "gui.refinedstorage.wireless_grid": "Draadloos rooster", "gui.refinedstorage.fluid_grid": "Vloeistof rooster", "gui.refinedstorage.disk_drive": "Schijf", "gui.refinedstorage.external_storage": "Externe opslag", "gui.refinedstorage.importer": "Importeur", "gui.refinedstorage.exporter": "Exporteur", "gui.refinedstorage.detector": "Detector", "gui.refinedstorage.destructor": "Destructor", "gui.refinedstorage.constructor": "Constructor", "gui.refinedstorage.relay": "Relais", "gui.refinedstorage.interface.import": "Interface Import", "gui.refinedstorage.interface.export": "Interface Export", "gui.refinedstorage.crafting_monitor": "Crafting Monitor", "gui.refinedstorage.crafting_monitor.machine_none": "Geen machine gevonden", "gui.refinedstorage.wireless_transmitter": "Draadloze zender", "gui.refinedstorage.wireless_transmitter.distance": "%d blokken", "gui.refinedstorage.crafter": "Crafter", "gui.refinedstorage.filter": "Filter", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.network_transmitter": "Netwerkzender", "gui.refinedstorage.network_transmitter.distance": "%d blokken", "gui.refinedstorage.network_transmitter.missing_card": "Geen netwerkkaart", "gui.refinedstorage.fluid_interface": "Vloeistof interface", "gui.refinedstorage.fluid_interface.in": "In", "gui.refinedstorage.fluid_interface.out": "Uit", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Vebruik: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Opgeslagen: %s", "misc.refinedstorage.storage.stored_capacity": "Opgeslagen: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% vol", "misc.refinedstorage.network_item.tooltip": "Gelinkt aan %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Er is geen draadloze zender binnen bereik.", "misc.refinedstorage.network_item.not_found": "Controller niet gevonden.", "misc.refinedstorage.network_card.tooltip": "Gelinkt aan %d, %d, %d in %s.", "misc.refinedstorage.pattern.inputs": "Inputs", "misc.refinedstorage.pattern.outputs": "Outputs", "misc.refinedstorage.pattern.invalid": "Ongeldig patroon", "misc.refinedstorage.start": "Start", "misc.refinedstorage.clear": "Legen", "misc.refinedstorage.cancel_all": "Annuleer alles", "misc.refinedstorage.priority": "Prioriteit", "sidebutton.refinedstorage.redstone_mode": "Redstone Mode", "sidebutton.refinedstorage.redstone_mode.0": "Redstone negeren", "sidebutton.refinedstorage.redstone_mode.1": "Alleen werken met redstone signaal", "sidebutton.refinedstorage.redstone_mode.2": "Alleen werken zonder redstone signaal", "sidebutton.refinedstorage.grid.view_type": "Weergave", "sidebutton.refinedstorage.grid.view_type.0": "Normaal", "sidebutton.refinedstorage.grid.view_type.1": "Geen craftables", "sidebutton.refinedstorage.grid.view_type.2": "Alleen craftables", "sidebutton.refinedstorage.grid.sorting.direction": "Sorteer richting", "sidebutton.refinedstorage.grid.sorting.direction.0": "Oplopend", "sidebutton.refinedstorage.grid.sorting.direction.1": "Aflopend", "sidebutton.refinedstorage.grid.sorting.type": "Sorteer type", "sidebutton.refinedstorage.grid.sorting.type.0": "Hoeveelheid", "sidebutton.refinedstorage.grid.sorting.type.1": "Naam", "sidebutton.refinedstorage.grid.search_box_mode": "Zoekbalkmodus", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normaal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normaal (autogeselecteerd)", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI gesynchronizeerd", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI gesynchronizeerd (autogeselecteerd)", "sidebutton.refinedstorage.mode": "Mode", "sidebutton.refinedstorage.mode.whitelist": "Whitelist", "sidebutton.refinedstorage.mode.blacklist": "Blacklist", "sidebutton.refinedstorage.iomode": "IO Mode", "sidebutton.refinedstorage.iomode.insert": "In netwerk steken", "sidebutton.refinedstorage.iomode.extract": "Uit netwerk halen", "sidebutton.refinedstorage.type": "Type", "sidebutton.refinedstorage.type.0": "Items", "sidebutton.refinedstorage.type.1": "Vloeistoffen", "sidebutton.refinedstorage.detector.mode": "Mode", "sidebutton.refinedstorage.detector.mode.0": "Redstone signaal aan wanneer onder het aantal", "sidebutton.refinedstorage.detector.mode.1": "Redstone signaal aan wanneer op het aantal", "sidebutton.refinedstorage.detector.mode.2": "Redstone signaal aan wanneer boven het aantal", "block.refinedstorage.controller": "Controller", "block.refinedstorage.creative_controller": "Creative Controller", "block.refinedstorage.cable": "Kabel", "block.refinedstorage.grid": "Rooster", "block.refinedstorage.crafting_grid": "Crafting rooster", "block.refinedstorage.pattern_grid": "Patroon rooster", "block.refinedstorage.fluid_grid": "Vloeistof rooster", "block.refinedstorage.disk_drive": "Schijf", "block.refinedstorage.disk_manipulator": "Schijf manipulator", "block.refinedstorage.external_storage": "Externe opslag", "block.refinedstorage.importer": "Importeur", "block.refinedstorage.exporter": "Exporteur", "block.refinedstorage.detector": "Detector", "block.refinedstorage.machine_casing": "Machine-omhulsel", "block.refinedstorage.destructor": "Destructor", "block.refinedstorage.constructor": "Constructor", "block.refinedstorage.1k_storage_block": "1k opslagblok", "block.refinedstorage.4k_storage_block": "4k opslagblok", "block.refinedstorage.16k_storage_block": "16k opslagblok", "block.refinedstorage.64k_storage_block": "64k opslagblok", "block.refinedstorage.creative_storage_block": "Creative opslagblok", "block.refinedstorage.relay": "Relais", "block.refinedstorage.interface": "Interface", "block.refinedstorage.crafting_monitor": "Crafting Monitor", "block.refinedstorage.wireless_transmitter": "Draadloze zender", "block.refinedstorage.crafter": "Crafter", "block.refinedstorage.network_receiver": "Netwerkontvanger", "block.refinedstorage.network_transmitter": "Netwerkzender", "block.refinedstorage.fluid_interface": "Vloeistof interface", "block.refinedstorage.64k_fluid_storage_block": "64k vloeistof opslagblok", "block.refinedstorage.256k_fluid_storage_block": "256k vloeistof opslagblok", "block.refinedstorage.1024k_fluid_storage_block": "1024k vloeistof opslagblok", "block.refinedstorage.4096k_fluid_storage_block": "4096k vloeistof opslagblok", "block.refinedstorage.creative_fluid_storage_block": "Creative vloeistof opslagblok", "item.refinedstorage.1k_storage_disk": "1k opslagschijf", "item.refinedstorage.4k_storage_disk": "4k opslagschijf", "item.refinedstorage.16k_storage_disk": "16k opslagschijf", "item.refinedstorage.64k_storage_disk": "64k opslagschijf", "item.refinedstorage.creative_storage_disk": "Creative opslagschijf", "item.refinedstorage.64k_fluid_storage_disk": "64k vloeistof opslagschijf", "item.refinedstorage.256k_fluid_storage_disk": "256k vloeistof opslagschijf", "item.refinedstorage.1024k_fluid_storage_disk": "1024k vloeistof opslagschijf", "item.refinedstorage.4096k_fluid_storage_disk": "4096k vloeistof opslagschijf", "item.refinedstorage.creative_fluid_storage_disk": "Creative vloeistof opslagschijf", "item.refinedstorage.wireless_grid": "Draadloos rooster", "item.refinedstorage.creative_wireless_grid": "Creative draadloos rooster", "item.refinedstorage.quartz_enriched_iron": "Quartz verrijkte ijzerstaaf", "item.refinedstorage.construction_core": "Constructiekern", "item.refinedstorage.destruction_core": "Destructiekern", "item.refinedstorage.silicon": "Siliconen", "item.refinedstorage.basic_processor": "Basis processor", "item.refinedstorage.improved_processor": "Verbeterde processor", "item.refinedstorage.advanced_processor": "Geavanceerde processor", "item.refinedstorage.1k_storage_part": "1k opslagdeel", "item.refinedstorage.4k_storage_part": "4k opslagdeel", "item.refinedstorage.16k_storage_part": "16k opslagdeel", "item.refinedstorage.64k_storage_part": "64k opslagdeel", "item.refinedstorage.64k_fluid_storage_part": "64k vloeistof opslagdeel", "item.refinedstorage.256k_fluid_storage_part": "256k vloeistof opslagdeel", "item.refinedstorage.1024k_fluid_storage_part": "1024k vloeistof opslagdeel", "item.refinedstorage.4096k_fluid_storage_part": "4096k vloeistof opslagdeel", "item.refinedstorage.pattern": "Patroon", "item.refinedstorage.upgrade": "Upgrade", "item.refinedstorage.range_upgrade": "Afstand upgrade", "item.refinedstorage.speed_upgrade": "Snelheid upgrade", "item.refinedstorage.crafting_upgrade": "Crafting upgrade", "item.refinedstorage.stack_upgrade": "Stack upgrade", "item.refinedstorage.storage_housing": "Opslagomhulsel", "item.refinedstorage.filter": "Filter", "item.refinedstorage.network_card": "Netwerkkaart" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/pl_pl.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Fasady z Refined Storage", "key.refinedstorage.focusSearchBar": "Przenieś kursor do paska wyszukiwania", "key.refinedstorage.clearGridCraftingMatrix": "Wyczyść siatkę konstruowania w terminalu", "key.refinedstorage.openWirelessGrid": "Otwórz bezprzewodowy terminal", "key.refinedstorage.openWirelessFluidGrid": "Otwórz bezprzewodowy terminal cieczy", "key.refinedstorage.openPortableGrid": "Otwórz przenośny terminal", "key.refinedstorage.openWirelessCraftingMonitor": "Otwórz bezprzewodowy monitor konstruowania", "gui.refinedstorage.controller": "Kontroler", "gui.refinedstorage.creative_controller": "Kreatywny kontroler", "gui.refinedstorage.grid": "Terminal", "gui.refinedstorage.grid.craft": "Wytwórz", "gui.refinedstorage.crafting_grid": "Terminal konstruowania", "gui.refinedstorage.pattern_grid": "Terminal szablonów", "gui.refinedstorage.grid.pattern_create": "Stwórz", "gui.refinedstorage.fluid_grid": "Terminal cieczy", "gui.refinedstorage.portable_grid": "Przenośny terminal", "gui.refinedstorage.item_amount": "Ilość przedmiotów", "gui.refinedstorage.fluid_amount": "Ilość płynów w mW", "gui.refinedstorage.disk_drive": "Napęd dyskowy", "gui.refinedstorage.disk_drive.disks": "Dyski", "gui.refinedstorage.disk_manipulator": "Manipulator dysków", "gui.refinedstorage.disk_manipulator.in": "Wejście", "gui.refinedstorage.disk_manipulator.out": "Wyjście", "gui.refinedstorage.external_storage": "Zewnętrzny magazyn", "gui.refinedstorage.importer": "Importer", "gui.refinedstorage.exporter": "Eksporter", "gui.refinedstorage.detector": "Detektor", "gui.refinedstorage.destructor": "Destruktor", "gui.refinedstorage.constructor": "Construktor", "gui.refinedstorage.relay": "Przekaźnik", "gui.refinedstorage.interface.import": "Importowanie do interfejsu", "gui.refinedstorage.interface.export": "Eksportowanie z interfejsu", "gui.refinedstorage.crafting_monitor": "Monitor konstruowania", "gui.refinedstorage.wireless_crafting_monitor": "Bezprzewodowy monitor konstruowania", "gui.refinedstorage.crafting_monitor.tooltip.requested": "%d zakończone", "gui.refinedstorage.crafting_monitor.stored": "Zmagazynowane: %d", "gui.refinedstorage.crafting_monitor.missing": "Brakujące: %d", "gui.refinedstorage.crafting_monitor.processing": "Przetwarzane: %d", "gui.refinedstorage.crafting_monitor.scheduled": "Zaplanowane: %d", "gui.refinedstorage.crafting_monitor.crafting": "Wytwarzane: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "Maszyna nie przyjmuje przedmiotu", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "Maszyna nie przyjmuje cieczy", "gui.refinedstorage.crafting_monitor.machine_none": "Nie znaleziono maszyny", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Przetwarzacz receptur jest zablokowany", "gui.refinedstorage.wireless_transmitter": "Nadajnik bezprzewodowy", "gui.refinedstorage.wireless_transmitter.distance": "%d bloków/bloki", "gui.refinedstorage.crafter": "Przetwarzacz receptur", "gui.refinedstorage.filter": "Filtr", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Filtr modów", "gui.refinedstorage.network_transmitter": "Nadajnik sieci", "gui.refinedstorage.network_transmitter.distance": "%d bloków/bloki", "gui.refinedstorage.network_transmitter.missing_card": "Brakuje karty sieciowej", "gui.refinedstorage.fluid_interface": "Interfejs płynów", "gui.refinedstorage.fluid_interface.in": "Wejście", "gui.refinedstorage.fluid_interface.out": "Wyjście", "gui.refinedstorage.crafting_preview": "Podgląd receptury", "gui.refinedstorage.crafting_preview.to_craft": "Do wytworzenia: %d", "gui.refinedstorage.crafting_preview.available": "Dostępne: %d", "gui.refinedstorage.crafting_preview.missing": "Brakujące: %d", "gui.refinedstorage.crafting_preview.error": "Żądanie nie wykonane", "gui.refinedstorage.crafting_preview.error.recursive.0": "Jeden ze składników potrzebował samego", "gui.refinedstorage.crafting_preview.error.recursive.1": "siebie.", "gui.refinedstorage.crafting_preview.error.recursive.2": "Musisz usunąć szablon lub upewnić się,", "gui.refinedstorage.crafting_preview.error.recursive.3": "że szablon nie jest używany w trakcie konstruowania.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Problemowy szablon:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "Zadanie konstruowania było zbyt skomplikowane", "gui.refinedstorage.crafting_preview.error.too_complex.1": "i zostało zakończone, by nie nadwyrężyć serwera.", "gui.refinedstorage.security_manager": "Menadżer bezpieczeństwa", "gui.refinedstorage.security_manager.configure": "Konfiguruj", "gui.refinedstorage.security_manager.permission.0": "Wkładanie", "gui.refinedstorage.security_manager.permission.0.tooltip": "Wkładanie przedmiotów lub cieczy do sieci", "gui.refinedstorage.security_manager.permission.1": "Zabieranie", "gui.refinedstorage.security_manager.permission.1.tooltip": "Zabieranie przedmiotów lub cieczy z sieci", "gui.refinedstorage.security_manager.permission.2": "Auto-wytwarzanie", "gui.refinedstorage.security_manager.permission.2.tooltip": "Rozpoczynanie, anulowanie i przeglądanie zadań konstruowania", "gui.refinedstorage.security_manager.permission.3": "Modyfikowanie", "gui.refinedstorage.security_manager.permission.3.tooltip": "Otwieranie i modyfikowanie bloków", "gui.refinedstorage.security_manager.permission.4": "Budowanie", "gui.refinedstorage.security_manager.permission.4.tooltip": "Dodawanie lub usuwanie urządzeń z sieci", "gui.refinedstorage.security_manager.permission.5": "Bezpieczeństwo", "gui.refinedstorage.security_manager.permission.5.tooltip": "Możliwość zmiany opcji bezpieczeństwa", "gui.refinedstorage.storage_monitor": "Monitor przechowywania", "gui.refinedstorage.crafter_manager": "Menadżer przetwarzaczy receptur", "gui.refinedstorage.alternatives": "Alternatywy", "gui.refinedstorage.alternatives.apply": "Zastosuj", "gui.refinedstorage.jei.transfer.autocrafting_available": "Auto-wytwarzanie dostępne", "gui.refinedstorage.jei.transfer.request_autocrafting": "CTRL + KLIKNIJ aby zażądać wytworzenia", "gui.refinedstorage.jei.transfer.request_autocrafting_mac": "CMD + KLIKNIJ aby zażądać wytworzenia", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Zużycie: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "Zmagazynowane: %s", "misc.refinedstorage.storage.stored_capacity": "Zmagazynowane: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "Pełne w %d%%", "misc.refinedstorage.network_item.tooltip": "Połączone z %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Brak nadajnika bezprzewodowego w zasięgu.", "misc.refinedstorage.network_item.not_found": "Sieć nie znaleziona.", "misc.refinedstorage.network_item.shortcut_not_found": "Brak przedmiotu \"%s\" w Twoim ekwipunku.", "misc.refinedstorage.network_item.shortcut_duplicate": "Jest więcej niż jeden przedmiot \"%s\" w Twoim ekwipunku.", "misc.refinedstorage.network_item.out_of_energy": "W przedmiocie \"%s\" skończyła się energia.", "misc.refinedstorage.network_card.tooltip": "Połączone z %d, %d, %d w wymiarze %s.", "misc.refinedstorage.pattern.inputs": "Przedmioty wejściowe", "misc.refinedstorage.pattern.outputs": "Przedmioty wyjściowe", "misc.refinedstorage.pattern.invalid": "Nieprawidłowy szablon", "misc.refinedstorage.pattern.exact": "Jest w trybie dokładnym", "misc.refinedstorage.pattern.allowed_item_tag": "Używa przedmiotów z %s dla %s", "misc.refinedstorage.pattern.allowed_fluid_tag": "Używa cieczy z %s dla %s", "misc.refinedstorage.pattern.error.processing_no_outputs": "Szablon przetwarzania nie posiada żadnych przedmiotów wyjściowych", "misc.refinedstorage.pattern.error.no_output": "Receptura nie ma żadnych przedmiotów wyjściowych", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "Receptura nie istnieje", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "Tag %s nie jest aplikowalny do %s", "misc.refinedstorage.security.no_permission": "Nie masz zezwolenia na wykonanie tej czynności.", "misc.refinedstorage.start": "Start", "misc.refinedstorage.clear": "Wyczyść", "misc.refinedstorage.set": "Ustaw", "misc.refinedstorage.cancel_all": "Anuluj wszystko", "misc.refinedstorage.priority": "Priorytet", "misc.refinedstorage.exact": "Dokładny", "misc.refinedstorage.processing": "Przetwarzanie", "misc.refinedstorage.total": "%s całości", "misc.refinedstorage.last_modified.just_now": "Ostatnio modyfikowany przed chwilą przez gracza %s", "misc.refinedstorage.last_modified.second": "Ostatnio modyfikowany %d sekundę temu przez gracza %s", "misc.refinedstorage.last_modified.seconds": "Ostatnio modyfikowany %d sekund(y) temu przez gracza %s", "misc.refinedstorage.last_modified.minute": "Ostatnio modyfikowany %d minutę temu przez gracza %s", "misc.refinedstorage.last_modified.minutes": "Ostatnio modyfikowany %d minut(y) temu przez gracza %s", "misc.refinedstorage.last_modified.hour": "Ostatnio modyfikowany %d godzinę temu przez gracza %s", "misc.refinedstorage.last_modified.hours": "Ostatnio modyfikowany %d godzin(y) temu przez gracza %s\n", "misc.refinedstorage.last_modified.day": "Ostatnio modyfikowany %d dzień temu przez gracza %s", "misc.refinedstorage.last_modified.days": "Ostatnio modyfikowany %d dni temu przez gracza %s", "misc.refinedstorage.last_modified.week": "Ostatnio modyfikowany %d tydzień temu przez gracza %s", "misc.refinedstorage.last_modified.weeks": "Ostatnio modyfikowany %d tygodni(e) temu przez gracza %s", "misc.refinedstorage.last_modified.year": "Ostatnio modyfikowany %d rok temu przez gracza %s", "misc.refinedstorage.last_modified.years": "Ostatnio modyfikowany %d lat(a) temu przez gracza %s", "sidebutton.refinedstorage.exact_mode": "Tryb dokładny", "sidebutton.refinedstorage.exact_mode.on": "Wł.", "sidebutton.refinedstorage.exact_mode.off": "Wył.", "sidebutton.refinedstorage.redstone_mode": "Tryb redstone", "sidebutton.refinedstorage.redstone_mode.0": "Ignoruj sygnał redstone", "sidebutton.refinedstorage.redstone_mode.1": "Działaj tylko z sygnałem redstone", "sidebutton.refinedstorage.redstone_mode.2": "Działaj tylko bez sygnału redstone", "sidebutton.refinedstorage.crafter_mode": "Tryb przetwarzacza receptur", "sidebutton.refinedstorage.crafter_mode.0": "Ignoruj sygnał redstone", "sidebutton.refinedstorage.crafter_mode.1": "Sygnał redstone odblokowuje auto-wytwarzanie", "sidebutton.refinedstorage.crafter_mode.2": "Sygnał redstone blokuje auto-wytwarzanie", "sidebutton.refinedstorage.crafter_mode.3": "Puls redstone dodaje następny zestaw", "sidebutton.refinedstorage.grid.view_type": "Widok", "sidebutton.refinedstorage.grid.view_type.0": "Normalny", "sidebutton.refinedstorage.grid.view_type.1": "Bez przedm. auto-wytwarzalnych", "sidebutton.refinedstorage.grid.view_type.2": "Tylko przedm. auto-wytwarzalne", "sidebutton.refinedstorage.grid.sorting.direction": "Kierunek sortowania", "sidebutton.refinedstorage.grid.sorting.direction.0": "Rosnący", "sidebutton.refinedstorage.grid.sorting.direction.1": "Malejący", "sidebutton.refinedstorage.grid.sorting.type": "Tryb sortowania", "sidebutton.refinedstorage.grid.sorting.type.0": "Ilość", "sidebutton.refinedstorage.grid.sorting.type.1": "Nazwa", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Ostatnio modyfikowany", "sidebutton.refinedstorage.grid.search_box_mode": "Tryb paska wyszukiwania", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normalny", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normalny (automatycznie wybrany)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Synchronizowany z JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Synchronizowany z JEI (automatycznie wybrany)", "sidebutton.refinedstorage.grid.search_box_mode.4": "Synchronizowany z JEI (dwukierunkowo)", "sidebutton.refinedstorage.grid.search_box_mode.5": "Synchronizowany z JEI (dwukierunkowo, automatycznie wybrany)", "sidebutton.refinedstorage.grid.size": "Rozmiar", "sidebutton.refinedstorage.grid.size.0": "Rozciągnij", "sidebutton.refinedstorage.grid.size.1": "Mały", "sidebutton.refinedstorage.grid.size.2": "Średni", "sidebutton.refinedstorage.grid.size.3": "Duży", "sidebutton.refinedstorage.mode": "Tryb", "sidebutton.refinedstorage.mode.whitelist": "Biała lista", "sidebutton.refinedstorage.mode.blacklist": "Czarna lista", "sidebutton.refinedstorage.iomode": "Tryb we.wy.", "sidebutton.refinedstorage.iomode.insert": "Wkładaj do sieci", "sidebutton.refinedstorage.iomode.extract": "Zabieraj z sieci", "sidebutton.refinedstorage.type": "Typ", "sidebutton.refinedstorage.type.0": "Przedmioty", "sidebutton.refinedstorage.type.1": "Ciecze", "sidebutton.refinedstorage.detector.mode": "Tryb", "sidebutton.refinedstorage.detector.mode.0": "Emituje sygnał kiedy poniżej ilości", "sidebutton.refinedstorage.detector.mode.1": "Emituje sygnał kiedy równy ilości", "sidebutton.refinedstorage.detector.mode.2": "Emituje sygnał kiedy powyżej ilości", "sidebutton.refinedstorage.constructor.drop": "Upuszczaj przedmioty zamiast stawiać", "sidebutton.refinedstorage.destructor.pickup": "Podnoś przedmioty zamiast niszczyć", "sidebutton.refinedstorage.access_type": "Tryb dostępu", "sidebutton.refinedstorage.access_type.0": "Wkładanie i zabieranie", "sidebutton.refinedstorage.access_type.1": "Tylko wkładanie", "sidebutton.refinedstorage.access_type.2": "Tylko zabieranie", "block.refinedstorage.controller": "Kontroler", "block.refinedstorage.creative_controller": "Kreatywny kontroler", "block.refinedstorage.cable": "Kabel", "block.refinedstorage.grid": "Terminal", "block.refinedstorage.crafting_grid": "Terminal konstruowania", "block.refinedstorage.pattern_grid": "Terminal szablonów", "block.refinedstorage.fluid_grid": "Terminal płynów", "block.refinedstorage.disk_drive": "Napęd dyskowy", "block.refinedstorage.disk_manipulator": "Manipulator dysków", "block.refinedstorage.external_storage": "Zewnętrzny magazyn", "block.refinedstorage.importer": "Importer", "block.refinedstorage.exporter": "Eksporter", "block.refinedstorage.detector": "Detektor", "block.refinedstorage.machine_casing": "Obudowa maszyn", "block.refinedstorage.destructor": "Destruktor", "block.refinedstorage.constructor": "Konstruktor", "block.refinedstorage.1k_storage_block": "Blok przechowywania 1k", "block.refinedstorage.4k_storage_block": "Blok przechowywania 4k", "block.refinedstorage.16k_storage_block": "Blok przechowywania 16k", "block.refinedstorage.64k_storage_block": "Blok przechowywania 64k", "block.refinedstorage.creative_storage_block": "Kreatywny blok przechowywania", "block.refinedstorage.relay": "Przekaźnik", "block.refinedstorage.interface": "Interfejs", "block.refinedstorage.crafting_monitor": "Monitor konstruowania", "block.refinedstorage.wireless_transmitter": "Nadajnik bezprzewodowy", "block.refinedstorage.crafter": "Przetwarzacz receptur", "block.refinedstorage.network_receiver": "Odbiornik sieci", "block.refinedstorage.network_transmitter": "Nadajnik sieci", "block.refinedstorage.fluid_interface": "Interfejs płynów", "block.refinedstorage.64k_fluid_storage_block": "Blok przechowywania cieczy 64k", "block.refinedstorage.256k_fluid_storage_block": "Blok przechowywania cieczy 256k", "block.refinedstorage.1024k_fluid_storage_block": "Blok przechowywania cieczy 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Blok przechowywania cieczy 4096k", "block.refinedstorage.creative_fluid_storage_block": "Kreatywny blok przechowywania cieczy", "block.refinedstorage.security_manager": "Menadżer bezpieczeństwa", "block.refinedstorage.quartz_enriched_iron_block": "Blok żelaza kwarcowego", "block.refinedstorage.storage_monitor": "Monitor przechowywania", "block.refinedstorage.portable_grid": "Przenośny terminal", "block.refinedstorage.creative_portable_grid": "Kreatywny przenośny terminal", "block.refinedstorage.portable_grid.tooltip": "Skradaj się aby postawić.", "block.refinedstorage.crafter_manager": "Menadżer przetwarzaczy receptur", "item.refinedstorage.1k_storage_disk": "Dysk przechowywania 1k", "item.refinedstorage.4k_storage_disk": "Dysk przechowywania 4k", "item.refinedstorage.16k_storage_disk": "Dysk przechowywania 16k", "item.refinedstorage.64k_storage_disk": "Dysk przechowywania 64k", "item.refinedstorage.creative_storage_disk": "Kreatywny dysk przechowywania", "item.refinedstorage.64k_fluid_storage_disk": "Dysk przechowywania cieczy 64k", "item.refinedstorage.256k_fluid_storage_disk": "Dysk przechowywania cieczy 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Dysk przechowywania cieczy 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Dysk przechowywania cieczy 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Kreatywny dysk przechowywania cieczy", "item.refinedstorage.wireless_grid": "Bezprzewodowy terminal", "item.refinedstorage.creative_wireless_grid": "Kreatywny bezprzewodowy terminal", "item.refinedstorage.wireless_fluid_grid": "Bezprzewodowy terminal cieczy", "item.refinedstorage.creative_wireless_fluid_grid": "Kreatywny bezprzewodowy terminal cieczy", "item.refinedstorage.wireless_crafting_monitor": "Bezprzewodowy monitor konstruowania", "item.refinedstorage.creative_wireless_crafting_monitor": "Kreatywny bezprzewodowy monitor konstruowania", "item.refinedstorage.quartz_enriched_iron": "Żelazo kwarcowe", "item.refinedstorage.construction_core": "Rdzeń konstrukcji", "item.refinedstorage.destruction_core": "Rdzeń destrukcji", "item.refinedstorage.silicon": "Silikon", "item.refinedstorage.raw_basic_processor": "Surowy podstawowy procesor", "item.refinedstorage.raw_improved_processor": "Surowy ulepszony procesor", "item.refinedstorage.raw_advanced_processor": "Surowy zaawansowany procesor", "item.refinedstorage.basic_processor": "Podstawowy procesor", "item.refinedstorage.improved_processor": "Ulepszony procesor", "item.refinedstorage.advanced_processor": "Zaawansowany procesor", "item.refinedstorage.1k_storage_part": "Pamięć przechowywania 1k", "item.refinedstorage.4k_storage_part": "Pamięć przechowywania 4k", "item.refinedstorage.16k_storage_part": "Pamięć przechowywania 16k", "item.refinedstorage.64k_storage_part": "Pamięć przechowywania 64k", "item.refinedstorage.64k_fluid_storage_part": "Pamięć przechowywania cieczy 64k", "item.refinedstorage.256k_fluid_storage_part": "Pamięć przechowywania cieczy 256k", "item.refinedstorage.1024k_fluid_storage_part": "Pamięć przechowywania cieczy 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Pamięć przechowywania cieczy 4096k", "item.refinedstorage.pattern": "Szablon", "item.refinedstorage.upgrade": "Ulepszenie", "item.refinedstorage.range_upgrade": "Ulepszenie zasięgu", "item.refinedstorage.speed_upgrade": "Ulepszenie szybkości", "item.refinedstorage.crafting_upgrade": "Ulepszenie konstruowania", "item.refinedstorage.stack_upgrade": "Ulepszenie stosu", "item.refinedstorage.silk_touch_upgrade": "Ulepszenie jedwabnego dotyku", "item.refinedstorage.fortune_1_upgrade": "Ulepszenie fortuny", "item.refinedstorage.fortune_2_upgrade": "Ulepszenie fortuny", "item.refinedstorage.fortune_3_upgrade": "Ulepszenie fortuny", "item.refinedstorage.regulator_upgrade": "Ulepszenie regulacyjne", "item.refinedstorage.storage_housing": "Obudowa dysku", "item.refinedstorage.filter": "Filtr", "item.refinedstorage.network_card": "Karta sieciowa", "item.refinedstorage.wrench": "Klucz", "item.refinedstorage.security_card": "Karta bezpieczeństwa", "item.refinedstorage.security_card.owner": "Przypisana do: %s", "item.refinedstorage.processor_binding": "Spoiwo procesora", "commands.refinedstorage.disk.create.error.disk_not_found": "NIe znaleziono dysku %s.", "commands.refinedstorage.disk.create.success": "Z powodzeniem oddano dysk %s dla %s.", "commands.refinedstorage.network.list.pos": "Lokalizacja sieci X: %d, Y: %d, Z: %d", "commands.refinedstorage.network.list.tick_times": "Mediana czasu ticku: %s ms. Mediana TPS: %s", "commands.refinedstorage.network.list.autocrafting_tasks": "%s zadań", "commands.refinedstorage.network.list.nodes": "%s instancji", "commands.refinedstorage.network.list.energy_usage": "Zużycie energii: %s", "commands.refinedstorage.network.get.error.not_found": "Nie znaleziono sieci.", "commands.refinedstorage.network.autocrafting.get.error.not_found": "Nie znaleziono zadania.", "commands.refinedstorage.network.autocrafting.cancel.single": "Anulowano %s zadanie.", "commands.refinedstorage.network.autocrafting.cancel.multiple": "Anulowano %s zadania/zadań.", "advancements.refinedstorage.controlling.description": "Wytwórz kontroler", "advancements.refinedstorage.connecting": "Połączenie", "advancements.refinedstorage.connecting.description": "Możesz ustawić wszystkie urządzenia obok siebie aby je połączyć, lub użyć kabla.", "advancements.refinedstorage.conditional_connecting": "Sterowanie połączeniem", "advancements.refinedstorage.conditional_connecting.description": "Wytwórz przekaźnik, aby kontrolować z pomocą redstone, połączenie w sieci", "advancements.refinedstorage.drives": "Dyski", "advancements.refinedstorage.drives.description": "Wytwórz napęd dyskowy aby móc przechowywać dyski", "advancements.refinedstorage.manipulating_disks": "Manipulowanie dyskami", "advancements.refinedstorage.manipulating_disks.description": "Użyj manipulatora dysków aby łatwo modyfikować zawartość dysków", "advancements.refinedstorage.storing_items": "Przechowywanie przedmiotów", "advancements.refinedstorage.storing_items.description": "Wytwórz dysk przechowywania i wsadź go do napędy dyskowego", "advancements.refinedstorage.viewing_items": "Przeglądanie przedmiotów", "advancements.refinedstorage.viewing_items.description": "Wytwórz terminal, aby mieć dostęp do zmagazynowanych przedmiotów", "advancements.refinedstorage.portable_storage": "Przenośne przechowywanie", "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ą", "advancements.refinedstorage.upgrading_your_grid": "Ulepszanie terminala", "advancements.refinedstorage.upgrading_your_grid.description": "Ulepsz swój terminal do terminalu konstruowania, aby mieć dostęp do siatki konstruowania bezpośrednio w terminalu", "advancements.refinedstorage.storing_fluids": "Przechowywanie cieczy", "advancements.refinedstorage.storing_fluids.description": "Wytwórz dysk przechowywania cieczy i wsadź go do napędy dyskowego", "advancements.refinedstorage.viewing_fluids": "Przeglądanie cieczy", "advancements.refinedstorage.viewing_fluids.description": "Wytwórz terminal cieczy, aby mieć dostęp do zmagazynowanych płynów", "advancements.refinedstorage.better_than_a_barrel": "Lepsze niż beczka", "advancements.refinedstorage.better_than_a_barrel.description": "Wytwórz monitor przechowywania, aby łatwo zarządzać pojedynczym przedmiotem", "advancements.refinedstorage.autocrafting": "Auto-wytwarzanie", "advancements.refinedstorage.autocrafting.description": "Wytwórz przetwarzacz receptur", "advancements.refinedstorage.pattern_creation": "Tworzenie szablonów", "advancements.refinedstorage.pattern_creation.description": "Konfiguruj szablony z użyciem terminala szablonów", "advancements.refinedstorage.monitoring": "Monitorowanie", "advancements.refinedstorage.monitoring.description": "Sprawdź status Twoich zadań konstruowania z pomocą monitora konstruowania", "advancements.refinedstorage.managing_patterns": "Zarządzanie szablonami", "advancements.refinedstorage.managing_patterns.description": "Wytwórz menadżer przetwarzaczy receptur, aby łatwiej zarządzać szablonami", "advancements.refinedstorage.importing": "Importowanie", "advancements.refinedstorage.importing.description": "Automatycznie importuj przedmioty lub ciecze do sieci z pomocą importera", "advancements.refinedstorage.destruction": "Niszczenie", "advancements.refinedstorage.destruction.description": "Automatycznie niszcz bloki lub podnoś ciecze i importuj je do sieci z pomocą destruktora", "advancements.refinedstorage.exporting": "Eksportowanie", "advancements.refinedstorage.exporting.description": "Automatycznie eksportuj przedmioty lub ciecze z sieci z pomocą eksportera", "advancements.refinedstorage.construction": "Konstrukcja", "advancements.refinedstorage.construction.description": "Automatycznie stawiaj bloki lub ciecze i importuj je do sieci z pomocą destruktora", "advancements.refinedstorage.security": "Bezpieczeństwo", "advancements.refinedstorage.security.description": "Zabezpiecz swoją sieć z pomocą menadżera i karty bezpieczeństwa", "advancements.refinedstorage.wireless": "Bezprzewodowo", "advancements.refinedstorage.wireless.description": "Nadawaj bezprzewodowy sygnał sieci z pomocą nadajnika bezprzewodowego", "advancements.refinedstorage.wireless_items": "Bezprzewodowe przedmioty", "advancements.refinedstorage.wireless_items.description": "Komunikuj się z siecią bezprzewodowo z pomocą bezprzewodowego terminala", "advancements.refinedstorage.wireless_fluids": "Bezprzewodowe ciecze", "advancements.refinedstorage.wireless_fluids.description": "Komunikuj się z siecią bezprzewodowo z pomocą bezprzewodowego terminala cieczy", "advancements.refinedstorage.wireless_monitoring": "Bezprzewodowe monitorowanie", "advancements.refinedstorage.wireless_monitoring.description": "Sprawdzaj status Twoich zadań konstruowania bezprzewodowo z pomocą bezprzewodowego monitora konstruowania", "advancements.refinedstorage.no_cables_required": "Kable są niepotrzebne", "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", "advancements.refinedstorage.upgrading": "Ulepszanie", "advancements.refinedstorage.upgrading.description": "Wytwórz ulepszenie aby polepszyć działanie różnych urządzeń", "advancements.refinedstorage.crafting_on_demand": "Konstruowanie na żądanie", "advancements.refinedstorage.crafting_on_demand.description": "Użyj ulepszenia konstruowania w interfejsie, eksporterze lub konstruktorze aby wytwarzać przedmioty na ich żądanie", "advancements.refinedstorage.detecting": "Detekcja", "advancements.refinedstorage.detecting.description": "Wykrywaj przedmioty lub ciecze w sieci z pomocą Detektora", "advancements.refinedstorage.interface_to_the_world": "Interfejs świata", "advancements.refinedstorage.interface_to_the_world.description": "Eksportuj i importuj przedmioty w tym samym czasie z pomocą interfejsu", "advancements.refinedstorage.storing_externally": "Zewnętrzne przechowywanie", "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" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/pt_br.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "key.refinedstorage.focusSearchBar": "Ir para a barra de pesquisa da grade.", "gui.refinedstorage.controller": "Controlador", "gui.refinedstorage.creative_controller": "Controlador (modo criativo)", "gui.refinedstorage.grid": "Grade", "gui.refinedstorage.grid.craft": "Fabricar", "gui.refinedstorage.crafting_grid": "Grade de fabricações", "gui.refinedstorage.pattern_grid": "Grade de padrões", "gui.refinedstorage.grid.pattern_create": "Criar padrão", "gui.refinedstorage.fluid_grid": "Grade de fluidos", "gui.refinedstorage.portable_grid": "Grade portátil", "gui.refinedstorage.disk_drive": "Drive", "gui.refinedstorage.disk_drive.disks": "Discos", "gui.refinedstorage.external_storage": "Armazenamento externo", "gui.refinedstorage.importer": "Importador", "gui.refinedstorage.exporter": "Exportador", "gui.refinedstorage.detector": "Detector", "gui.refinedstorage.destructor": "Destruidor", "gui.refinedstorage.constructor": "Construtor", "gui.refinedstorage.relay": "Retransmissor", "gui.refinedstorage.interface.import": "Interface de importação", "gui.refinedstorage.interface.export": "Interface de exportação", "gui.refinedstorage.crafting_monitor": "Monitor de fabricações", "gui.refinedstorage.wireless_crafting_monitor": "Monitor de fabricações sem fio", "gui.refinedstorage.crafting_monitor.machine_none": "Nenhuma máquina encontrada", "gui.refinedstorage.wireless_transmitter": "Transmissor sem fio", "gui.refinedstorage.wireless_transmitter.distance": "%d blocos", "gui.refinedstorage.crafter": "Fabricador", "gui.refinedstorage.filter": "Filtro", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Filtrar mod", "gui.refinedstorage.network_transmitter": "Transmissor de rede", "gui.refinedstorage.network_transmitter.distance": "%d blocos", "gui.refinedstorage.network_transmitter.missing_card": "Ausência de cartão de rede", "gui.refinedstorage.fluid_interface": "Interface de fluidos", "gui.refinedstorage.fluid_interface.in": "Entrada", "gui.refinedstorage.fluid_interface.out": "Saída", "gui.refinedstorage.crafting_preview": "Pré-visualização da fabricação", "gui.refinedstorage.crafting_preview.to_craft": "Para fabricar: %d", "gui.refinedstorage.crafting_preview.available": "Disponível: %d", "gui.refinedstorage.crafting_preview.missing": "Ausência de: %d", "gui.refinedstorage.crafting_preview.circular": "Dependência circular!", "gui.refinedstorage.crafting_preview.loop": "Loop em processamento...", "gui.refinedstorage.security_manager": "Gerenciador de segurança", "gui.refinedstorage.security_manager.configure": "Configurar", "gui.refinedstorage.security_manager.permission.0": "Inserir", "gui.refinedstorage.security_manager.permission.0.tooltip": "Inserindo itens na rede", "gui.refinedstorage.security_manager.permission.1": "Extrair", "gui.refinedstorage.security_manager.permission.1.tooltip": "Extraindo itens da rede", "gui.refinedstorage.security_manager.permission.2": "Auto-fabricação", "gui.refinedstorage.security_manager.permission.2.tooltip": "Iniciando, cancelando e visualizando tarefas de fabricação", "gui.refinedstorage.security_manager.permission.3": "Modificar", "gui.refinedstorage.security_manager.permission.3.tooltip": "Abrindo interfaces do bloco", "gui.refinedstorage.security_manager.permission.4": "Fabricar", "gui.refinedstorage.security_manager.permission.4.tooltip": "Adicionando ou removendo dispositivos para ou a partir da rede", "gui.refinedstorage.security_manager.permission.5": "Segurança", "gui.refinedstorage.security_manager.permission.5.tooltip": "Capacidade de alterar as opções de segurança", "gui.refinedstorage.storage_monitor": "Monitor de armazenamento", "misc.refinedstorage.energy_stored": "%d / %d RF", "misc.refinedstorage.energy_usage": "Uso: %d RF/t", "misc.refinedstorage.energy_usage_minimal": "%d RF/t", "misc.refinedstorage.storage.stored": "Stored: %s", "misc.refinedstorage.storage.stored_capacity": "Stored: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% cheio", "misc.refinedstorage.network_item.tooltip": "Ligado a %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "Não há transmissor sem fio no alcance.", "misc.refinedstorage.network_item.not_found": "Controlador não encontrado.", "misc.refinedstorage.network_card.tooltip": "Conectado a %d, %d, %d em %s.", "misc.refinedstorage.pattern.inputs": "Entradas", "misc.refinedstorage.pattern.outputs": "Saídas", "misc.refinedstorage.pattern.invalid": "Padrão inválido", "misc.refinedstorage.security.no_permission": "Você não possui permissão para executar essa ação.", "misc.refinedstorage.start": "Começar", "misc.refinedstorage.clear": "Limpar", "misc.refinedstorage.set": "Definir", "misc.refinedstorage.cancel_all": "Cancelar tudo", "misc.refinedstorage.priority": "Prioridade", "misc.refinedstorage.processing": "Processamento", "sidebutton.refinedstorage.redstone_mode": "Modo de redstone", "sidebutton.refinedstorage.redstone_mode.0": "Ignorar o sinal de redstone", "sidebutton.refinedstorage.redstone_mode.1": "Apenas funcionar com sinal de redstone", "sidebutton.refinedstorage.redstone_mode.2": "Apenas funcionar sem sinal de redstone", "sidebutton.refinedstorage.grid.view_type": "Exibição", "sidebutton.refinedstorage.grid.view_type.0": "Normal", "sidebutton.refinedstorage.grid.view_type.1": "Apenas não fabricáveis", "sidebutton.refinedstorage.grid.view_type.2": "Apenas fabricáveis", "sidebutton.refinedstorage.grid.sorting.direction": "Direção da classificação", "sidebutton.refinedstorage.grid.sorting.direction.0": "Ascendente", "sidebutton.refinedstorage.grid.sorting.direction.1": "Descendente", "sidebutton.refinedstorage.grid.sorting.type": "Tipo da classificação", "sidebutton.refinedstorage.grid.sorting.type.0": "Quantidade", "sidebutton.refinedstorage.grid.sorting.type.1": "Nome", "sidebutton.refinedstorage.grid.sorting.type.2": "Id", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.search_box_mode": "Modo da caixa de pesquisa", "sidebutton.refinedstorage.grid.search_box_mode.0": "Normal", "sidebutton.refinedstorage.grid.search_box_mode.1": "Normal (auto-seleção)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Sincronizado com JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Sincronizado com JEI (auto-seleção)", "sidebutton.refinedstorage.grid.size": "Tamanho", "sidebutton.refinedstorage.grid.size.0": "Esticado", "sidebutton.refinedstorage.grid.size.1": "Pequeno", "sidebutton.refinedstorage.grid.size.2": "Médio", "sidebutton.refinedstorage.grid.size.3": "Grande", "sidebutton.refinedstorage.mode": "Modo", "sidebutton.refinedstorage.mode.whitelist": "Lista branca", "sidebutton.refinedstorage.mode.blacklist": "Lista negra", "sidebutton.refinedstorage.iomode": "Modo IO", "sidebutton.refinedstorage.iomode.insert": "Inserir na rede", "sidebutton.refinedstorage.iomode.extract": "Extrair da rede", "sidebutton.refinedstorage.type": "Tipo", "sidebutton.refinedstorage.type.0": "Itens", "sidebutton.refinedstorage.type.1": "Fluidos", "sidebutton.refinedstorage.detector.mode": "Modo", "sidebutton.refinedstorage.detector.mode.0": "Emite um sinal quando estiver abaixo do valor", "sidebutton.refinedstorage.detector.mode.1": "Emite um sinal quando estiver no valor", "sidebutton.refinedstorage.detector.mode.2": "Emite um sinal quando estiver acima do valor", "sidebutton.refinedstorage.constructor.drop": "Soltar os blocos em vez de colocar", "sidebutton.refinedstorage.destructor.pickup": "Pegue os itens em vez de quebrar", "sidebutton.refinedstorage.access_type": "Tipo de acesso", "sidebutton.refinedstorage.access_type.0": "Inserir e extrair", "sidebutton.refinedstorage.access_type.1": "Inserir apenas", "sidebutton.refinedstorage.access_type.2": "Extrair apenas", "block.refinedstorage.controller": "Controlador", "block.refinedstorage.creative_controller": "Controlador (modo criativo)", "block.refinedstorage.cable": "Cabo", "block.refinedstorage.grid": "Grade", "block.refinedstorage.crafting_grid": "Grade de fabricações", "block.refinedstorage.pattern_grid": "Grade de padrões", "block.refinedstorage.fluid_grid": "Grade de fluidos", "block.refinedstorage.disk_drive": "Unidade de disco", "block.refinedstorage.disk_manipulator": "Manipulador de disco", "block.refinedstorage.external_storage": "Armazenamento externo", "block.refinedstorage.importer": "Importador", "block.refinedstorage.exporter": "Exportador", "block.refinedstorage.detector": "Detector", "block.refinedstorage.machine_casing": "Gabinete de máquina", "block.refinedstorage.destructor": "Destruidor", "block.refinedstorage.constructor": "Construtor", "block.refinedstorage.1k_storage_block": "Bloco de armazenamento 1k", "block.refinedstorage.4k_storage_block": "Bloco de armazenamento 4k", "block.refinedstorage.16k_storage_block": "Bloco de armazenamento 16k", "block.refinedstorage.64k_storage_block": "Bloco de armazenamento 64k", "block.refinedstorage.creative_storage_block": "Bloco de armazenamento (modo criativo)", "block.refinedstorage.relay": "Retransmissor", "block.refinedstorage.interface": "Interface", "block.refinedstorage.crafting_monitor": "Monitor de fabricações", "block.refinedstorage.wireless_transmitter": "Transmissor wireless", "block.refinedstorage.wireless_transmitter.tooltip": "Precisa ser colocado em %s.", "block.refinedstorage.crafter": "Fabricador", "block.refinedstorage.network_receiver": "Receptor de rede", "block.refinedstorage.network_transmitter": "Transmissor de rede", "block.refinedstorage.fluid_interface": "Interface de fluidos", "block.refinedstorage.64k_fluid_storage_block": "Bloco de armazenamento de fluidos 64k", "block.refinedstorage.256k_fluid_storage_block": "Bloco de armazenamento de fluidos 256k", "block.refinedstorage.1024k_fluid_storage_block": "Bloco de armazenamento de fluidos 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Bloco de armazenamento de fluidos 4096k", "block.refinedstorage.creative_fluid_storage_block": "Bloco de armazenamento de fluidos (modo criativo)", "block.refinedstorage.security_manager": "Gerenciador de segurança", "block.refinedstorage.quartz_enriched_iron_block": "Bloco de ferro enriquecido com quartzo", "block.refinedstorage.storage_monitor": "Monitor de armazenamento", "block.refinedstorage.portable_grid": "Grade portátil", "block.refinedstorage.creative_portable_grid": "Grade portátil (modo criativo)", "block.refinedstorage.portable_grid.tooltip": "Esgueirar-se para colocar no mundo.", "item.refinedstorage.1k_storage_disk": "Disco de armazenamento 1k", "item.refinedstorage.4k_storage_disk": "Disco de armazenamento 4k", "item.refinedstorage.16k_storage_disk": "Disco de armazenamento 16k", "item.refinedstorage.64k_storage_disk": "Disco de armazenamento 64k", "item.refinedstorage.creative_storage_disk": "Disco de armazenamento (modo criativo)", "item.refinedstorage.64k_fluid_storage_disk": "Disco de armazenamento de fluidos 64k", "item.refinedstorage.256k_fluid_storage_disk": "Disco de armazenamento de fluidos 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Disco de armazenamento de fluidos 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Disco de armazenamento de fluidos 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Disco de armazenamento de fluidos (modo criativo)", "item.refinedstorage.wireless_grid": "Grade sem fio", "item.refinedstorage.creative_wireless_grid": "Grade sem fio (modo criativo)", "item.refinedstorage.wireless_fluid_grid": "Grade de fluidos sem fio", "item.refinedstorage.creative_wireless_fluid_grid": "Grade de fluidos sem fio (modo criativo)", "item.refinedstorage.wireless_crafting_monitor": "Monitor de fabricações sem fio", "item.refinedstorage.creative_wireless_crafting_monitor": "Monitor de fabricações sem fio (modo criativo)", "item.refinedstorage.quartz_enriched_iron": "Ferro enriquecido com quartzo", "item.refinedstorage.construction_core": "Núcleo de construção", "item.refinedstorage.destruction_core": "Núcleo de destruição", "item.refinedstorage.silicon": "Silício", "item.refinedstorage.basic_processor": "Processador básico", "item.refinedstorage.improved_processor": "Processador melhorado", "item.refinedstorage.advanced_processor": "Processador avançado", "item.refinedstorage.1k_storage_part": "Parte de armazenamento 1k", "item.refinedstorage.4k_storage_part": "Parte de armazenamento 4k", "item.refinedstorage.16k_storage_part": "Parte de armazenamento 16k", "item.refinedstorage.64k_storage_part": "Parte de armazenamento 64k", "item.refinedstorage.64k_fluid_storage_part": "Parte de armazenamento de fluidos 64k", "item.refinedstorage.256k_fluid_storage_part": "Parte de armazenamento de fluidos 256k", "item.refinedstorage.1024k_fluid_storage_part": "Parte de armazenamento de fluidos 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Parte de armazenamento de fluidos 4096k", "item.refinedstorage.pattern": "Padrão", "item.refinedstorage.upgrade": "Aprimoramento", "item.refinedstorage.range_upgrade": "Aprimoramento de alcance", "item.refinedstorage.speed_upgrade": "Aprimoramento de velocidade", "item.refinedstorage.crafting_upgrade": "Aprimoramento de fabricação", "item.refinedstorage.stack_upgrade": "Aprimoramento de empilhamento", "item.refinedstorage.silk_touch_upgrade": "Aprimoramento de toque suave", "item.refinedstorage.fortune_1_upgrade": "Aprimoramento de fortuna", "item.refinedstorage.fortune_2_upgrade": "Aprimoramento de fortuna", "item.refinedstorage.fortune_3_upgrade": "Aprimoramento de fortuna", "item.refinedstorage.storage_housing": "Alojamento de armazenação", "item.refinedstorage.filter": "Filtro", "item.refinedstorage.wrench": "Chave inglesa", "item.refinedstorage.network_card": "Cartão de rede", "item.refinedstorage.security_card": "Cartão de segurança", "item.refinedstorage.security_card.owner": "Ligado a: %s", "advancements.refinedstorage.controlling.description": "Fabrique um controlador.", "advancements.refinedstorage.connecting": "Conectando!", "advancements.refinedstorage.connecting.description": "Você pode colocar todos os dispositivos próximos uns dos outros para conectá-los, ou pode usar os cabos.", "advancements.refinedstorage.conditional_connecting": "Conexão condicional!", "advancements.refinedstorage.conditional_connecting.description": "Fabrique um retransmissor, você pode passar o sinal de rede usando sinal de redstone.", "advancements.refinedstorage.drives": "Drives!", "advancements.refinedstorage.drives.description": "Fabrique uma unidade de disco para poder armazenar seus discos.", "advancements.refinedstorage.manipulating_disks": "Manipulando discos!", "advancements.refinedstorage.manipulating_disks.description": "Use um manipulador de disco para modificar facilmente conteúdos de discos.", "advancements.refinedstorage.storing_items": "Armazenando itens!", "advancements.refinedstorage.storing_items.description": "Fabrique um disco de armazenamento e coloque em sua unidade de disco.", "advancements.refinedstorage.viewing_items": "Visualizando itens!", "advancements.refinedstorage.viewing_items.description": "Fabrique uma grade para interagir com seu armazenamento de itens.", "advancements.refinedstorage.portable_storage": "Armazenamento portátil!", "advancements.refinedstorage.upgrading_your_grid": "Aprimorando sua grade!", "advancements.refinedstorage.upgrading_your_grid.description": "Aprimore sua grade para uma grade de fabricações para obter habilidades de fabricar na sua grade.", "advancements.refinedstorage.storing_fluids": "Armazenando fluidos!", "advancements.refinedstorage.storing_fluids.description": "Fabrique um disco de armazenamento de fluidos e coloque em sua unidade de disco.", "advancements.refinedstorage.viewing_fluids": "Visualizando fluidos!", "advancements.refinedstorage.viewing_fluids.description": "Fabrique uma grade de fluidos para interagir com o seu armazenamento de fluidos.", "advancements.refinedstorage.better_than_a_barrel": "Melhor do que um barril!", "advancements.refinedstorage.better_than_a_barrel.description": "Fabrique um monitor de armazenamento para visualizar, inserir ou extrair itens de uma rede.", "advancements.refinedstorage.autocrafting": "Auto-fabricação!", "advancements.refinedstorage.autocrafting.description": "Fabrique um fabricador.", "advancements.refinedstorage.pattern_creation": "Criação de padrões!", "advancements.refinedstorage.pattern_creation.description": "Crie padrões com uma grade de padrões e um padrão.", "advancements.refinedstorage.monitoring": "Monitoramento!", "advancements.refinedstorage.monitoring.description": "Verifique os status das suas tarefas de fabricação com um monitor de fabricações.", "advancements.refinedstorage.importing": "Importação!", "advancements.refinedstorage.importing.description": "Obtenha itens ou fluidos da rede de armazenamento com um importador.", "advancements.refinedstorage.destruction": "Destruição!", "advancements.refinedstorage.destruction.description": "Obtenha blocos ou fluidos da rede de armazenamento com um destruidor.", "advancements.refinedstorage.exporting": "Exportação!", "advancements.refinedstorage.exporting.description": "Obtenha itens ou fluidos fora da rede de armazenamento com um exportador.", "advancements.refinedstorage.construction": "Construção!", "advancements.refinedstorage.construction.description": "Obtenha blocos ou fluidos fora da rede de armazenamento com um construtor.", "advancements.refinedstorage.security": "Segurança!", "advancements.refinedstorage.security.description": "Proteja sua rede com um gerente de segurança e um cartão de segurança.", "advancements.refinedstorage.wireless": "Wireless!", "advancements.refinedstorage.wireless.description": "Transmita um sinal de rede com um transmissor wireless.", "advancements.refinedstorage.wireless_items": "Itens wireless!", "advancements.refinedstorage.wireless_items.description": "Interaja com o seu armazenamento de itens wireless com uma grade wireless.", "advancements.refinedstorage.wireless_fluids": "Fluidos wireless!", "advancements.refinedstorage.wireless_fluids.description": "Interaja com o seu armazenamento de fluidos wireless com uma grade de fluidos wireless.", "advancements.refinedstorage.wireless_monitoring": "Monitoramento wireless!", "advancements.refinedstorage.wireless_monitoring.description": "Verifique o status de suas tarefas de fabricação wireless com um monitor de fabricações wireless.", "advancements.refinedstorage.no_cables_required": "Não são necessários cabos!", "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.", "advancements.refinedstorage.upgrading": "Aprimorando!", "advancements.refinedstorage.upgrading.description": "Fabrique um aprimoramento.", "advancements.refinedstorage.crafting_on_demand": "Fabrique sob demanda!", "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.", "advancements.refinedstorage.detecting": "Detecção!", "advancements.refinedstorage.detecting.description": "Detectar itens ou fluidos da rede com o detector.", "advancements.refinedstorage.interface_to_the_world": "Interface para o mundo!", "advancements.refinedstorage.storing_externally": "Armazenando externamente!", "advancements.refinedstorage.storing_externally.description": "Use um armazenamento externo para fornecer à rede o armazenamento de um bloco externo como um baú." } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/ru_ru.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage: Фасады", "key.refinedstorage.focusSearchBar": "Фокусировка на панели поиска", "key.refinedstorage.clearGridCraftingMatrix": "Очистить сетку создания", "key.refinedstorage.openWirelessGrid": "Открыть беспроводной терминал", "key.refinedstorage.openWirelessFluidGrid": "Открыть жидкостный беспроводной терминал", "key.refinedstorage.openPortableGrid": "Открыть переносной терминал", "key.refinedstorage.openWirelessCraftingMonitor": "Открыть беспроводной монитор создания", "gui.refinedstorage.controller": "Контроллер", "gui.refinedstorage.creative_controller": "Творческий контроллер", "gui.refinedstorage.grid": "Терминал", "gui.refinedstorage.grid.craft": "+", "gui.refinedstorage.crafting_grid": "Терминал", "gui.refinedstorage.pattern_grid": "Терминал", "gui.refinedstorage.grid.pattern_create": "Создать шаблон", "gui.refinedstorage.fluid_grid": "Терминал", "gui.refinedstorage.portable_grid": "Переносной терминал", "gui.refinedstorage.item_amount": "Количество предмета", "gui.refinedstorage.fluid_amount": "Количество жидкости в mB", "gui.refinedstorage.disk_drive": "Дисковый привод", "gui.refinedstorage.disk_drive.disks": "Диски", "gui.refinedstorage.disk_manipulator": "Дисковый манипулятор", "gui.refinedstorage.disk_manipulator.in": "В", "gui.refinedstorage.disk_manipulator.out": "Из", "gui.refinedstorage.external_storage": "Шина внешнего хранения", "gui.refinedstorage.importer": "Шина импорта", "gui.refinedstorage.exporter": "Шина экспорта", "gui.refinedstorage.detector": "Детектор", "gui.refinedstorage.destructor": "Шина разрушения", "gui.refinedstorage.constructor": "Шина формирования", "gui.refinedstorage.relay": "Реле", "gui.refinedstorage.interface.import": "Интерфейс импорта", "gui.refinedstorage.interface.export": "Интерфейс экспорта", "gui.refinedstorage.crafting_monitor": "Монитор создания", "gui.refinedstorage.wireless_crafting_monitor": "Беспроводной монитор создания", "gui.refinedstorage.crafting_monitor.tooltip.requested": "Запросили %d", "gui.refinedstorage.crafting_monitor.stored": "В наличии: %d", "gui.refinedstorage.crafting_monitor.missing": "Отсутствует: %d", "gui.refinedstorage.crafting_monitor.processing": "Обработка: %d", "gui.refinedstorage.crafting_monitor.scheduled": "Запланировано: %d", "gui.refinedstorage.crafting_monitor.crafting": "Создание: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "Механизм не принимает предмет", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "Механизм не принимает жидкость", "gui.refinedstorage.crafting_monitor.machine_none": "Механизм не найден", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "Сборщик заблокирован", "gui.refinedstorage.wireless_transmitter": "Беспроводной передатчик", "gui.refinedstorage.wireless_transmitter.distance": "%d блок(ов)", "gui.refinedstorage.crafter": "Сборщик", "gui.refinedstorage.filter": "Фильтр", "gui.refinedstorage.filter.compare_nbt": "Учитывать NBT", "gui.refinedstorage.filter.mod_filter": "Фильтровать по моду", "gui.refinedstorage.network_transmitter": "Сетевой передатчик", "gui.refinedstorage.network_transmitter.distance": "%d блок(ов)", "gui.refinedstorage.network_transmitter.missing_card": "Не найдена сетевая карта", "gui.refinedstorage.fluid_interface": "Жидкостный интерфейс", "gui.refinedstorage.fluid_interface.in": "В", "gui.refinedstorage.fluid_interface.out": "Из", "gui.refinedstorage.crafting_preview": "Предварительный просмотр", "gui.refinedstorage.crafting_preview.to_craft": "Создать: %d", "gui.refinedstorage.crafting_preview.available": "Доступно: %d", "gui.refinedstorage.crafting_preview.missing": "Отсутствует: %d", "gui.refinedstorage.crafting_preview.error": "Не удаётся создать", "gui.refinedstorage.crafting_preview.error.recursive.0": "Не хватает ингридиентов, чтобы завершить", "gui.refinedstorage.crafting_preview.error.recursive.1": "создание.", "gui.refinedstorage.crafting_preview.error.recursive.2": "Вам нужно удалить шаблон или убедиться, что", "gui.refinedstorage.crafting_preview.error.recursive.3": "шаблон не используется во время автосоздания.", "gui.refinedstorage.crafting_preview.error.recursive.4": "Шаблон повреждён:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "Расчёт задачи по автосозданию был слишком сложным", "gui.refinedstorage.crafting_preview.error.too_complex.1": "и был остановлен, чтобы избежать нагрузки на сервер.", "gui.refinedstorage.security_manager": "Менеджер безопасности", "gui.refinedstorage.security_manager.configure": "Настроить", "gui.refinedstorage.security_manager.permission.0": "Помещать", "gui.refinedstorage.security_manager.permission.0.tooltip": "Помещение предметов в сеть", "gui.refinedstorage.security_manager.permission.1": "Извлекать", "gui.refinedstorage.security_manager.permission.1.tooltip": "Извлечение предметов из сети", "gui.refinedstorage.security_manager.permission.2": "Автосоздание", "gui.refinedstorage.security_manager.permission.2.tooltip": "Запуск, отмена и просмотр задач автосоздания", "gui.refinedstorage.security_manager.permission.3": "Изменять", "gui.refinedstorage.security_manager.permission.3.tooltip": "Открытие блоков с интерфейсом", "gui.refinedstorage.security_manager.permission.4": "Строить", "gui.refinedstorage.security_manager.permission.4.tooltip": "Добавление или удаление устройств сети", "gui.refinedstorage.security_manager.permission.5": "Безопасность", "gui.refinedstorage.security_manager.permission.5.tooltip": "Изменение параметров безопасности", "gui.refinedstorage.storage_monitor": "Монитор хранения", "gui.refinedstorage.crafter_manager": "Менеджер создания", "gui.refinedstorage.alternatives": "Альтернативы", "gui.refinedstorage.alternatives.apply": "Применить", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "Используется: %d FE/тик", "misc.refinedstorage.energy_usage_minimal": "%d FE/тик", "misc.refinedstorage.storage.stored": "Запасено: %s", "misc.refinedstorage.storage.stored_capacity": "Запасено: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "Заполнено на %d%%", "misc.refinedstorage.network_item.tooltip": "Связан с %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "В зоне действия нет беспроводного передатчика.", "misc.refinedstorage.network_item.not_found": "Контроллер не найден.", "misc.refinedstorage.network_item.shortcut_not_found": "В вашем инвентаре нет ни одного %s.", "misc.refinedstorage.network_item.shortcut_duplicate": "В вашем инвентаре есть более одного %s.", "misc.refinedstorage.network_item.out_of_energy": "У «%s» недостаточно энергии.", "misc.refinedstorage.network_card.tooltip": "Связана с %d, %d, %d в %s.", "misc.refinedstorage.pattern.inputs": "На входе:", "misc.refinedstorage.pattern.outputs": "На выходе:", "misc.refinedstorage.pattern.invalid": "Недопустимый шаблон", "misc.refinedstorage.pattern.exact": "Использует точный режим", "misc.refinedstorage.pattern.allowed_item_tag": "Использует предметы из %s для %s", "misc.refinedstorage.pattern.allowed_fluid_tag": "Использует жидкости из %s для %s", "misc.refinedstorage.pattern.error.processing_no_outputs": "Шаблон обработки не имеет «выходов»", "misc.refinedstorage.pattern.error.no_output": "Рецепт не имеет «выхода»", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "Рецепт не существует", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "Тег %s больше не применим к %s", "misc.refinedstorage.security.no_permission": "У вас нет разрешения на выполнение этого действия.", "misc.refinedstorage.start": "Начать", "misc.refinedstorage.clear": "Очистить", "misc.refinedstorage.set": "Установить", "misc.refinedstorage.cancel_all": "Отменить все", "misc.refinedstorage.priority": "Приоритет", "misc.refinedstorage.exact": "Точно", "misc.refinedstorage.processing": "Обработка", "misc.refinedstorage.total": "Всего: %s", "misc.refinedstorage.last_modified.just_now": "Последнее изменение только что %s", "misc.refinedstorage.last_modified.second": "Последнее изменение %d секунду назад %s", "misc.refinedstorage.last_modified.seconds": "Последнее изменение %d секунд назад %s", "misc.refinedstorage.last_modified.minute": "Последнее изменение %d минуту назад %s", "misc.refinedstorage.last_modified.minutes": "Последнее изменение %d минут назад %s", "misc.refinedstorage.last_modified.hour": "Последнее изменение %d час назад %s", "misc.refinedstorage.last_modified.hours": "Последнее изменение %d часов назад %s", "misc.refinedstorage.last_modified.day": "Последнее изменение %d день назад %s", "misc.refinedstorage.last_modified.days": "Последнее изменение %d дней назад %s", "misc.refinedstorage.last_modified.week": "Последнее изменение %d неделю назад %s", "misc.refinedstorage.last_modified.weeks": "Последнее изменение %d недель назад %s", "misc.refinedstorage.last_modified.year": "Последнее изменение %d год назад %s", "misc.refinedstorage.last_modified.years": "Последнее изменение %d лет назад %s", "sidebutton.refinedstorage.exact_mode": "Точный режим", "sidebutton.refinedstorage.exact_mode.on": "Вкл.", "sidebutton.refinedstorage.exact_mode.off": "Выкл.", "sidebutton.refinedstorage.redstone_mode": "Режим редстоуна", "sidebutton.refinedstorage.redstone_mode.0": "Игнорировать редстоун-сигнал", "sidebutton.refinedstorage.redstone_mode.1": "Работать только с редстоун-сигналом", "sidebutton.refinedstorage.redstone_mode.2": "Работать только без редстоун-сигнала", "sidebutton.refinedstorage.crafter_mode": "Режим сборщика", "sidebutton.refinedstorage.crafter_mode.0": "Игнорировать редстоун-сигнал", "sidebutton.refinedstorage.crafter_mode.1": "При подаче редстоун-сигнала разблокирует автосоздание", "sidebutton.refinedstorage.crafter_mode.2": "При подаче редстоун-сигнала блокирует автосоздание", "sidebutton.refinedstorage.crafter_mode.3": "При подаче редстоун-импульса поставляет следующий набор", "sidebutton.refinedstorage.grid.view_type": "Отображение", "sidebutton.refinedstorage.grid.view_type.0": "Обычное", "sidebutton.refinedstorage.grid.view_type.1": "Без шаблонов", "sidebutton.refinedstorage.grid.view_type.2": "Только шаблоны", "sidebutton.refinedstorage.grid.sorting.direction": "Порядок сортировки", "sidebutton.refinedstorage.grid.sorting.direction.0": "По возрастанию", "sidebutton.refinedstorage.grid.sorting.direction.1": "По убыванию", "sidebutton.refinedstorage.grid.sorting.type": "Сортировка по", "sidebutton.refinedstorage.grid.sorting.type.0": "Количеству", "sidebutton.refinedstorage.grid.sorting.type.1": "Названию", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "Inventory Tweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "Последнему изменению", "sidebutton.refinedstorage.grid.search_box_mode": "Режим панели поиска", "sidebutton.refinedstorage.grid.search_box_mode.0": "Обычный", "sidebutton.refinedstorage.grid.search_box_mode.1": "Обычный (автовыбор)", "sidebutton.refinedstorage.grid.search_box_mode.2": "Синхронизированный с JEI", "sidebutton.refinedstorage.grid.search_box_mode.3": "Синхронизированный с JEI (автовыбор)", "sidebutton.refinedstorage.grid.size": "Размер", "sidebutton.refinedstorage.grid.size.0": "Вытянутый", "sidebutton.refinedstorage.grid.size.1": "Маленький", "sidebutton.refinedstorage.grid.size.2": "Средний", "sidebutton.refinedstorage.grid.size.3": "Большой", "sidebutton.refinedstorage.mode": "Режим", "sidebutton.refinedstorage.mode.whitelist": "Белый список", "sidebutton.refinedstorage.mode.blacklist": "Чёрный список", "sidebutton.refinedstorage.iomode": "Режим ввода/вывода", "sidebutton.refinedstorage.iomode.insert": "Помещать в сеть", "sidebutton.refinedstorage.iomode.extract": "Извлекать из сети", "sidebutton.refinedstorage.type": "Тип", "sidebutton.refinedstorage.type.0": "Предметы", "sidebutton.refinedstorage.type.1": "Жидкости", "sidebutton.refinedstorage.detector.mode": "Режим", "sidebutton.refinedstorage.detector.mode.0": "Излучать сигнал, если количество меньше", "sidebutton.refinedstorage.detector.mode.1": "Излучать сигнал, если количество равно", "sidebutton.refinedstorage.detector.mode.2": "Излучать сигнал, если количество больше", "sidebutton.refinedstorage.constructor.drop": "Выбрасывать блоки вместо размещения", "sidebutton.refinedstorage.destructor.pickup": "Подбирать предметы, а не ломать", "sidebutton.refinedstorage.access_type": "Тип доступа", "sidebutton.refinedstorage.access_type.0": "Помещать и извлекать", "sidebutton.refinedstorage.access_type.1": "Только помещать", "sidebutton.refinedstorage.access_type.2": "Только извлекать", "block.refinedstorage.controller": "Контроллер", "block.refinedstorage.creative_controller": "Творческий контроллер", "block.refinedstorage.cable": "Кабель", "block.refinedstorage.grid": "Терминал", "block.refinedstorage.crafting_grid": "Терминал создания", "block.refinedstorage.pattern_grid": "Терминал с кодировщиком шаблонов", "block.refinedstorage.fluid_grid": "Жидкостный терминал", "block.refinedstorage.disk_drive": "Дисковый привод", "block.refinedstorage.disk_manipulator": "Дисковый манипулятор", "block.refinedstorage.external_storage": "Шина внешнего хранения", "block.refinedstorage.importer": "Шина импорта", "block.refinedstorage.exporter": "Шина экспорта", "block.refinedstorage.detector": "Детектор", "block.refinedstorage.machine_casing": "Корпус механизма", "block.refinedstorage.destructor": "Шина разрушения", "block.refinedstorage.constructor": "Шина формирования", "block.refinedstorage.1k_storage_block": "Блок хранения 1k", "block.refinedstorage.4k_storage_block": "Блок хранения 4k", "block.refinedstorage.16k_storage_block": "Блок хранения 16k", "block.refinedstorage.64k_storage_block": "Блок хранения 64k", "block.refinedstorage.creative_storage_block": "Творческий блок хранения", "block.refinedstorage.relay": "Реле", "block.refinedstorage.interface": "Интерфейс", "block.refinedstorage.crafting_monitor": "Монитор создания", "block.refinedstorage.wireless_transmitter": "Беспроводной передатчик", "block.refinedstorage.wireless_transmitter.tooltip": "Необходимо поставить на %s.", "block.refinedstorage.crafter": "Сборщик", "block.refinedstorage.network_receiver": "Сетевой приёмник", "block.refinedstorage.network_transmitter": "Сетевой передатчик", "block.refinedstorage.fluid_interface": "Жидкостный интерфейс", "block.refinedstorage.64k_fluid_storage_block": "Блок хранения жидкости 64k", "block.refinedstorage.256k_fluid_storage_block": "Блок хранения жидкости 256k", "block.refinedstorage.1024k_fluid_storage_block": "Блок хранения жидкости 1024k", "block.refinedstorage.4096k_fluid_storage_block": "Блок хранения жидкости 4096k", "block.refinedstorage.creative_fluid_storage_block": "Творческий блок хранения жидкости", "block.refinedstorage.security_manager": "Менеджер безопасности", "block.refinedstorage.quartz_enriched_iron_block": "Блок обогащённого кварцем железа", "block.refinedstorage.storage_monitor": "Монитор хранения", "block.refinedstorage.portable_grid": "Переносной терминал", "block.refinedstorage.creative_portable_grid": "Творческий переносной терминал", "block.refinedstorage.portable_grid.tooltip": "Нужно красться, чтобы поставить в мире.", "block.refinedstorage.crafter_manager": "Менеджер создания", "item.refinedstorage.1k_storage_disk": "Диск хранения 1k", "item.refinedstorage.4k_storage_disk": "Диск хранения 4k", "item.refinedstorage.16k_storage_disk": "Диск хранения 16k", "item.refinedstorage.64k_storage_disk": "Диск хранения 64k", "item.refinedstorage.creative_storage_disk": "Творческий диск хранения", "item.refinedstorage.64k_fluid_storage_disk": "Диск хранения жидкости 64k", "item.refinedstorage.256k_fluid_storage_disk": "Диск хранения жидкости 256k", "item.refinedstorage.1024k_fluid_storage_disk": "Диск хранения жидкости 1024k", "item.refinedstorage.4096k_fluid_storage_disk": "Диск хранения жидкости 4096k", "item.refinedstorage.creative_fluid_storage_disk": "Творческий диск хранения жидкости", "item.refinedstorage.wireless_grid": "Беспроводной терминал", "item.refinedstorage.creative_wireless_grid": "Творческий беспроводной терминал", "item.refinedstorage.wireless_fluid_grid": "Беспроводной жидкостный терминал", "item.refinedstorage.creative_wireless_fluid_grid": "Творческий беспроводной жидкостный терминал", "item.refinedstorage.wireless_crafting_monitor": "Беспроводной монитор создания", "item.refinedstorage.creative_wireless_crafting_monitor": "Творческий беспроводной монитор создания", "item.refinedstorage.quartz_enriched_iron": "Обогащённое кварцем железо", "item.refinedstorage.construction_core": "Ядро формирования", "item.refinedstorage.destruction_core": "Ядро разрушения", "item.refinedstorage.silicon": "Кремний", "item.refinedstorage.raw_basic_processor": "Необработанный базовый процессор", "item.refinedstorage.raw_improved_processor": "Необработанный улучшенный процессор", "item.refinedstorage.raw_advanced_processor": "Необработанный продвинутый процессор", "item.refinedstorage.basic_processor": "Базовый процессор", "item.refinedstorage.improved_processor": "Улучшенный процессор", "item.refinedstorage.advanced_processor": "Продвинутый процессор", "item.refinedstorage.1k_storage_part": "Компонент хранения 1k", "item.refinedstorage.4k_storage_part": "Компонент хранения 4k", "item.refinedstorage.16k_storage_part": "Компонент хранения 16k", "item.refinedstorage.64k_storage_part": "Компонент хранения 64k", "item.refinedstorage.64k_fluid_storage_part": "Жидкостный компонент хранения 64k", "item.refinedstorage.256k_fluid_storage_part": "Жидкостный компонент хранения 256k", "item.refinedstorage.1024k_fluid_storage_part": "Жидкостный компонент хранения 1024k", "item.refinedstorage.4096k_fluid_storage_part": "Жидкостный компонент хранения 4096k", "item.refinedstorage.pattern": "Шаблон", "item.refinedstorage.upgrade": "Корпус улучшения", "item.refinedstorage.range_upgrade": "Улучшение «Радиус»", "item.refinedstorage.speed_upgrade": "Улучшение «Скорость»", "item.refinedstorage.crafting_upgrade": "Улучшение «Создание»", "item.refinedstorage.stack_upgrade": "Улучшение «Стопка»", "item.refinedstorage.silk_touch_upgrade": "Улучшение «Шёлковое касание»", "item.refinedstorage.fortune_1_upgrade": "Улучшение «Удача»", "item.refinedstorage.fortune_2_upgrade": "Улучшение «Удача»", "item.refinedstorage.fortune_3_upgrade": "Улучшение «Удача»", "item.refinedstorage.regulator_upgrade": "Улучшение «Регулятор»", "item.refinedstorage.storage_housing": "Корпус диска", "item.refinedstorage.filter": "Фильтр", "item.refinedstorage.network_card": "Сетевая карта", "item.refinedstorage.wrench": "Гаечный ключ", "item.refinedstorage.security_card": "Карта безопасности", "item.refinedstorage.security_card.owner": "Привязана к %s", "item.refinedstorage.processor_binding": "Связующий процессорный компонент", "commands.refinedstorage.disk.create.error.disk_not_found": "Диск %s не был найден.", "commands.refinedstorage.disk.create.success": "Диск %s успешно выдан %s.", "advancements.refinedstorage.controlling.description": "Создайте контроллер", "advancements.refinedstorage.connecting": "Соединение", "advancements.refinedstorage.connecting.description": "Вы можете разместить все устройства вплотную друг с другом или использовать кабели, чтобы соединить их", "advancements.refinedstorage.conditional_connecting": "Условное соединение", "advancements.refinedstorage.conditional_connecting.description": "Создайте реле, которое позволяет соединять или разъединять сетевой сигнал с помощью редстоуна", "advancements.refinedstorage.drives": "Приводы", "advancements.refinedstorage.drives.description": "Создайте дисковый привод, чтобы иметь возможность хранить свои диски", "advancements.refinedstorage.manipulating_disks": "Управление дисками", "advancements.refinedstorage.manipulating_disks.description": "Используйте дисковый манипулятор, чтобы легко изменять содержимое дисков", "advancements.refinedstorage.storing_items": "Хранение предметов", "advancements.refinedstorage.storing_items.description": "Создайте диск хранения и поместите его в дисковый привод", "advancements.refinedstorage.viewing_items": "Просмотр предметов", "advancements.refinedstorage.viewing_items.description": "Создайте терминал для доступа к вашему хранилищу предметов", "advancements.refinedstorage.portable_storage": "Портативное хранение", "advancements.refinedstorage.portable_storage.description": "Создайте переносной терминал для доступа к предметам и жидкостям на дисках, без подключения к сети", "advancements.refinedstorage.upgrading_your_grid": "Обновите свой терминал", "advancements.refinedstorage.upgrading_your_grid.description": "Улучшите ваш терминал до терминала создания, чтобы получить возможность создавать прямо в нём", "advancements.refinedstorage.storing_fluids": "Хранение жидкостей", "advancements.refinedstorage.storing_fluids.description": "Создайте диск хранения жидкости и поместите его в дисковый привод", "advancements.refinedstorage.viewing_fluids": "Просмотр жидкостей", "advancements.refinedstorage.viewing_fluids.description": "Создайте жидкостный терминал для доступа к вашему хранилищу жидкостей", "advancements.refinedstorage.better_than_a_barrel": "Лучше, чем бочка", "advancements.refinedstorage.better_than_a_barrel.description": "Создайте монитор хранения, чтобы просматривать предметы сети и вручную помещать или извлекать их", "advancements.refinedstorage.autocrafting": "Автосоздание", "advancements.refinedstorage.autocrafting.description": "Создайте сборщик", "advancements.refinedstorage.pattern_creation": "Создание шаблонов", "advancements.refinedstorage.pattern_creation.description": "Создайте шаблоны с помощью терминала с кодировщиком шаблонов", "advancements.refinedstorage.monitoring": "Мониторинг", "advancements.refinedstorage.monitoring.description": "Проверьте прогресс автосоздания с помощью монитора создания", "advancements.refinedstorage.managing_patterns": "Управление шаблонами", "advancements.refinedstorage.managing_patterns.description": "Создайте менеджер создания, чтобы лучше управлять своими шаблонами", "advancements.refinedstorage.importing": "Импорт", "advancements.refinedstorage.importing.description": "Используйте шину импорта для ввода предметов или жидкостей в сеть", "advancements.refinedstorage.destruction": "Разрушение", "advancements.refinedstorage.destruction.description": "Используйте шину разрушения для сбора блоков или жидкостей в сеть", "advancements.refinedstorage.exporting": "Экспорт", "advancements.refinedstorage.exporting.description": "Используйте шину экспорта для вывода предметов или жидкостей из сети", "advancements.refinedstorage.construction": "Строительство", "advancements.refinedstorage.construction.description": "Используйте шину формирования для размещения предметов или жидкостей из сети", "advancements.refinedstorage.security": "Безопасность", "advancements.refinedstorage.security.description": "Защитите свою сеть с помощью менеджера безопасности и карты безопасности", "advancements.refinedstorage.wireless": "Беспроводной", "advancements.refinedstorage.wireless.description": "Передайте сетевой сигнал с помощью беспроводного передатчика", "advancements.refinedstorage.wireless_items": "Беспроводная передача предметов", "advancements.refinedstorage.wireless_items.description": "Используйте беспроводной терминал для удалённого доступа к вашим предметам сети", "advancements.refinedstorage.wireless_fluids": "Беспроводная передача жидкостей", "advancements.refinedstorage.wireless_fluids.description": "Используйте беспроводной жидкостный терминал для удалённого доступа к вашим жидкостям сети", "advancements.refinedstorage.wireless_monitoring": "Беспроводной мониторинг", "advancements.refinedstorage.wireless_monitoring.description": "Проверьте прогресс автосоздания с помощью беспроводного монитора создания", "advancements.refinedstorage.no_cables_required": "Кабели не требуются!", "advancements.refinedstorage.no_cables_required.description": "Используйте сетевой передатчик, сетевой приёмник и сетевую карту, чтобы добавить дополнительные устройства в сеть без использования кабелей", "advancements.refinedstorage.upgrading": "Модернизация!", "advancements.refinedstorage.upgrading.description": "Создайте улучшения для различных устройств", "advancements.refinedstorage.crafting_on_demand": "Создание по запросу", "advancements.refinedstorage.crafting_on_demand.description": "Используйте улучшение «Создание» в интерфейсе, шине экспорта или шине формирования для создания предметов по запросу", "advancements.refinedstorage.detecting": "Обнаружение", "advancements.refinedstorage.detecting.description": "Используйте детектор, чтобы обнаружить предметы или жидкости в сети", "advancements.refinedstorage.interface_to_the_world": "Интерфейс к миру", "advancements.refinedstorage.interface_to_the_world.description": "Экспортируйте и импортируйте предметы одновременно с помощью интерфейса", "advancements.refinedstorage.storing_externally": "Внешнее хранение", "advancements.refinedstorage.storing_externally.description": "Используйте шину внешнего хранения для подключения к сети внешнего хранилища, например сундука" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/zh_cn.json ================================================ { "itemGroup.refinedstorage": "Refined Storage", "itemGroup.refinedstorage.covers": "Refined Storage 伪装板", "key.refinedstorage.focusSearchBar": "跳转终端搜索条", "key.refinedstorage.clearGridCraftingMatrix": "清空合成网格", "key.refinedstorage.openWirelessGrid": "打开无线面板", "key.refinedstorage.openWirelessFluidGrid": "打开无线流体面板", "key.refinedstorage.openPortableGrid": "打开便携面板", "key.refinedstorage.openWirelessCraftingMonitor": "打开无线合成监控面板", "gui.refinedstorage.controller": "控制器", "gui.refinedstorage.creative_controller": "创造控制器", "gui.refinedstorage.grid": "终端", "gui.refinedstorage.grid.craft": "合成", "gui.refinedstorage.crafting_grid": "合成终端", "gui.refinedstorage.pattern_grid": "模板终端", "gui.refinedstorage.grid.pattern_create": "写入磁盘", "gui.refinedstorage.fluid_grid": "流体终端", "gui.refinedstorage.item_amount": "物品数量", "gui.refinedstorage.fluid_amount": "流体量以mB为单位", "gui.refinedstorage.disk_drive": "驱动器", "gui.refinedstorage.disk_drive.disks": "磁盘", "gui.refinedstorage.external_storage": "外部存储总线", "gui.refinedstorage.importer": "输入总线", "gui.refinedstorage.exporter": "输出总线", "gui.refinedstorage.detector": "网络物品检测器", "gui.refinedstorage.destructor": "破坏面板", "gui.refinedstorage.constructor": "成型面板", "gui.refinedstorage.relay": "继电器", "gui.refinedstorage.interface.import": "输入端", "gui.refinedstorage.interface.export": "输出端", "gui.refinedstorage.crafting_monitor": "合成监控处理器", "gui.refinedstorage.wireless_crafting_monitor": "无线合成监控处理器", "gui.refinedstorage.crafting_monitor.tooltip.requested": "需要 %d", "gui.refinedstorage.crafting_monitor.stored": "已存储: %d", "gui.refinedstorage.crafting_monitor.missing": "缺失: %d", "gui.refinedstorage.crafting_monitor.processing": "处理中: %d", "gui.refinedstorage.crafting_monitor.scheduled": "已调度: %d", "gui.refinedstorage.crafting_monitor.crafting": "合成中: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "机器不接受物品", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "机器不接受流体", "gui.refinedstorage.crafting_monitor.machine_none": "找不到机器", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "合成被锁定", "gui.refinedstorage.wireless_transmitter": "无线访问点", "gui.refinedstorage.wireless_transmitter.distance": "%d 方块", "gui.refinedstorage.crafter": "装配室", "gui.refinedstorage.filter": "终端过滤", "gui.refinedstorage.filter.compare_damage": "耐久", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "Mod过滤", "gui.refinedstorage.network_transmitter": "网络变送器", "gui.refinedstorage.network_transmitter.distance": "%d 个方块", "gui.refinedstorage.network_transmitter.dimension": "维度 %d", "gui.refinedstorage.network_transmitter.missing_card": "缺失网卡", "gui.refinedstorage.fluid_interface": "流体面板", "gui.refinedstorage.fluid_interface.in": "输入", "gui.refinedstorage.fluid_interface.out": "输出", "gui.refinedstorage.crafting_preview": "合成预览", "gui.refinedstorage.crafting_preview.to_craft": "制作:%d", "gui.refinedstorage.crafting_preview.available": "可用:%d", "gui.refinedstorage.crafting_preview.missing": "缺失:%d", "gui.refinedstorage.crafting_preview.error": "请求失败", "gui.refinedstorage.crafting_preview.error.recursive.0": "其中一种制作成分最终需要", "gui.refinedstorage.crafting_preview.error.recursive.1": "自己.", "gui.refinedstorage.crafting_preview.error.recursive.2": "您需要删除该模式或确保", "gui.refinedstorage.crafting_preview.error.recursive.3": "在制作过程中不使用模式.", "gui.refinedstorage.crafting_preview.error.recursive.4": "违规模式:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "制作任务计算过于复杂,", "gui.refinedstorage.crafting_preview.error.too_complex.1": "并且已停止以缓解服务器压力。", "gui.refinedstorage.reader": "读取器", "gui.refinedstorage.writer": "写入器", "gui.refinedstorage.security_manager": "权限管理器", "gui.refinedstorage.security_manager.configure": "配置", "gui.refinedstorage.security_manager.permission.0": "输入", "gui.refinedstorage.security_manager.permission.0.tooltip": "向网络中输入物品", "gui.refinedstorage.security_manager.permission.1": "输出", "gui.refinedstorage.security_manager.permission.1.tooltip": "从网络中输出物品", "gui.refinedstorage.security_manager.permission.2": "自动合成", "gui.refinedstorage.security_manager.permission.2.tooltip": "开始、取消、预览合成任务", "gui.refinedstorage.security_manager.permission.3": "修改", "gui.refinedstorage.security_manager.permission.3.tooltip": "打开方块的GUI", "gui.refinedstorage.security_manager.permission.4": "操纵", "gui.refinedstorage.security_manager.permission.4.tooltip": "向网络中添加、移除设备", "gui.refinedstorage.security_manager.permission.5": "安全", "gui.refinedstorage.security_manager.permission.5.tooltip": "改变安全选项", "gui.refinedstorage.storage_monitor": "存储监控器", "gui.refinedstorage.portable_grid": "便携式终端", "gui.refinedstorage.crafter_manager": "合成管理器", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "使用: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "已存储: %s", "misc.refinedstorage.storage.stored_capacity": "已存储: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% 已使用", "misc.refinedstorage.network_item.tooltip": "连接到 %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "在范围内没有可以接入的无线访问点.", "misc.refinedstorage.network_item.not_found": "没找到控制器.", "misc.refinedstorage.network_card.tooltip": "连接到 %d, %d, %d.", "misc.refinedstorage.pattern.inputs": "输入", "misc.refinedstorage.pattern.outputs": "输出", "misc.refinedstorage.pattern.invalid": "无效模式", "misc.refinedstorage.pattern.oredict": "使用矿物辞典", "misc.refinedstorage.security.no_permission": "你没有权限进行此操作", "misc.refinedstorage.start": "开始", "misc.refinedstorage.clear": "清除", "misc.refinedstorage.set": "设置", "misc.refinedstorage.cancel_all": "取消所有", "misc.refinedstorage.priority": "优先级", "misc.refinedstorage.oredict": "矿物辞典", "misc.refinedstorage.processing": "进行中", "misc.refinedstorage.reader_writer.redstone": "红石强度:%d", "misc.refinedstorage.total": "总共 %s", "misc.refinedstorage.last_modified.just_now": "刚刚被 %s 操作", "misc.refinedstorage.last_modified.second": "%d 秒前被 %s 操作", "misc.refinedstorage.last_modified.seconds": "%d 秒前被 %s 操作", "misc.refinedstorage.last_modified.minute": "%d 分钟前被 %s 操作", "misc.refinedstorage.last_modified.minutes": "%d 分钟前被 %s 操作", "misc.refinedstorage.last_modified.hour": "%d 小时前被 %s 操作", "misc.refinedstorage.last_modified.hours": "%d 小时前被 %s 操作", "misc.refinedstorage.last_modified.day": "%d 天前被 %s 操作", "misc.refinedstorage.last_modified.days": "%d 天前被 %s 操作", "misc.refinedstorage.last_modified.week": "%d 周前被 %s 操作", "misc.refinedstorage.last_modified.weeks": "%d 周前被 %s 操作", "misc.refinedstorage.last_modified.year": "%d 年前被 %s 操作", "misc.refinedstorage.last_modified.years": "%d 年前被 %s 操作", "sidebutton.refinedstorage.compare.1": "耐久匹配", "sidebutton.refinedstorage.compare.2": "NBT匹配", "sidebutton.refinedstorage.redstone_mode": "红石模式", "sidebutton.refinedstorage.redstone_mode.0": "忽略红石信号", "sidebutton.refinedstorage.redstone_mode.1": "有红石信号时工作", "sidebutton.refinedstorage.redstone_mode.2": "无红石信号时工作", "sidebutton.refinedstorage.crafter_mode": "合成模式", "sidebutton.refinedstorage.crafter_mode.0": "无视红石信号", "sidebutton.refinedstorage.crafter_mode.1": "红石信号解锁自动合成", "sidebutton.refinedstorage.crafter_mode.2": "红石信号锁定自动合成", "sidebutton.refinedstorage.crafter_mode.3": "红石脉冲插入下一组", "sidebutton.refinedstorage.grid.view_type": "显示", "sidebutton.refinedstorage.grid.view_type.0": "默认", "sidebutton.refinedstorage.grid.view_type.1": "隐藏合成", "sidebutton.refinedstorage.grid.view_type.2": "只有合成", "sidebutton.refinedstorage.grid.sorting.direction": "排序方式", "sidebutton.refinedstorage.grid.sorting.direction.0": "上升", "sidebutton.refinedstorage.grid.sorting.direction.1": "下降", "sidebutton.refinedstorage.grid.sorting.type": "排序按", "sidebutton.refinedstorage.grid.sorting.type.0": "数量", "sidebutton.refinedstorage.grid.sorting.type.1": "名字", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "最后修改时间", "sidebutton.refinedstorage.grid.search_box_mode": "搜索框模式", "sidebutton.refinedstorage.grid.search_box_mode.0": "标准搜索", "sidebutton.refinedstorage.grid.search_box_mode.1": "自动搜索", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI 标准同步", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI 自动同步", "sidebutton.refinedstorage.grid.size": "大小", "sidebutton.refinedstorage.grid.size.0": "自适应", "sidebutton.refinedstorage.grid.size.1": "小", "sidebutton.refinedstorage.grid.size.2": "中", "sidebutton.refinedstorage.grid.size.3": "大", "sidebutton.refinedstorage.mode": "模式", "sidebutton.refinedstorage.mode.whitelist": "白名单", "sidebutton.refinedstorage.mode.blacklist": "黑名单", "sidebutton.refinedstorage.iomode": "IO模式", "sidebutton.refinedstorage.iomode.insert": "输入到网络", "sidebutton.refinedstorage.iomode.extract": "从网络输出", "sidebutton.refinedstorage.type": "类型", "sidebutton.refinedstorage.type.0": "物品", "sidebutton.refinedstorage.type.1": "流体", "sidebutton.refinedstorage.detector.mode": "模式", "sidebutton.refinedstorage.detector.mode.0": "物品数量小于输入数量时输出信号", "sidebutton.refinedstorage.detector.mode.1": "物品数量等于输入数量时输出信号", "sidebutton.refinedstorage.detector.mode.2": "物品数量大于于输入数量时输出信号", "sidebutton.refinedstorage.constructor.drop": "将物品以掉落物形式抛出", "sidebutton.refinedstorage.destructor.pickup": "拾取物品模式", "sidebutton.refinedstorage.access_type": "访问类型", "sidebutton.refinedstorage.access_type.0": "输入输出", "sidebutton.refinedstorage.access_type.1": "仅输入", "sidebutton.refinedstorage.access_type.2": "仅输出", "block.refinedstorage.controller": "控制器", "block.refinedstorage.creative_controller": "创造控制器", "block.refinedstorage.cable": "线缆", "block.refinedstorage.grid": "终端", "block.refinedstorage.crafting_grid": "合成终端", "block.refinedstorage.pattern_grid": "样板终端", "block.refinedstorage.fluid_grid": "流体终端", "block.refinedstorage.disk_drive": "磁盘驱动器", "block.refinedstorage.disk_manipulator": "磁盘操纵器", "block.refinedstorage.external_storage": "外部存储总线", "block.refinedstorage.importer": "输入总线", "block.refinedstorage.exporter": "输出总线", "block.refinedstorage.detector": "标准发信器", "block.refinedstorage.machine_casing": "机器外壳", "block.refinedstorage.destructor": "破坏面板", "block.refinedstorage.constructor": "成型面板", "block.refinedstorage.1k_storage_block": "1k 存储方块", "block.refinedstorage.4k_storage_block": "4k 存储方块", "block.refinedstorage.16k_storage_block": "16k 存储方块", "block.refinedstorage.64k_storage_block": "64k 存储方块", "block.refinedstorage.creative_storage_block": "创造存储方块", "block.refinedstorage.relay": "继电器", "block.refinedstorage.interface": "物品传输接口", "block.refinedstorage.crafting_monitor": "合成监控处理器", "block.refinedstorage.wireless_transmitter": "无线访问点", "block.refinedstorage.wireless_transmitter.tooltip": "需要放置在%s上。", "block.refinedstorage.crafter": "装配室", "block.refinedstorage.network_receiver": "网络接收器", "block.refinedstorage.network_transmitter": "网络变送器", "block.refinedstorage.fluid_interface": "流体面板", "block.refinedstorage.64k_fluid_storage_block": "64k 流体存储方块", "block.refinedstorage.256k_fluid_storage_block": "256k 流体存储方块", "block.refinedstorage.1024k_fluid_storage_block": "1024k 流体存储方块", "block.refinedstorage.4096k_fluid_storage_block": "4096k 流体存储方块", "block.refinedstorage.creative_fluid_storage_block": "创造流体存储方块", "block.refinedstorage.reader": "读取器", "block.refinedstorage.writer": "写入器", "block.refinedstorage.security_manager": "权限管理器", "block.refinedstorage.quartz_enriched_iron_block": "富石英块", "block.refinedstorage.storage_monitor": "存储监控器", "block.refinedstorage.portable_grid": "便携式终端", "block.refinedstorage.creative_portable_grid": "创造便携式终端", "block.refinedstorage.portable_grid.tooltip": "Shift进行放置", "block.refinedstorage.crafter_manager": "合成管理器", "item.refinedstorage.raw_basic_processor": "未处理基础处理器", "item.refinedstorage.raw_improved_processor": "未处理进阶处理器", "item.refinedstorage.raw_advanced_processor": "未处理高级处理器", "item.refinedstorage.1k_storage_disk": "1k 存储磁盘", "item.refinedstorage.4k_storage_disk": "4k 存储磁盘", "item.refinedstorage.16k_storage_disk": "16k 存储磁盘", "item.refinedstorage.64k_storage_disk": "64k 存储磁盘", "item.refinedstorage.creative_storage_disk": "创造存储磁盘", "item.refinedstorage.storage_disk.5": "调试用存储磁盘", "item.refinedstorage.64k_fluid_storage_disk": "64k 流体存储磁盘", "item.refinedstorage.256k_fluid_storage_disk": "256k 流体存储磁盘", "item.refinedstorage.1024k_fluid_storage_disk": "1024k 流体存储磁盘", "item.refinedstorage.4096k_fluid_storage_disk": "4096k 流体存储磁盘", "item.refinedstorage.creative_fluid_storage_disk": "创造流体存储磁盘", "item.refinedstorage.fluid_storage_disk.5": "调试用流体存储磁盘", "item.refinedstorage.wireless_grid": "无线终端", "item.refinedstorage.creative_wireless_grid": "创造无线终端", "item.refinedstorage.wireless_fluid_grid": "无线流体终端", "item.refinedstorage.creative_wireless_fluid_grid": "创造无线流体终端", "item.refinedstorage.wireless_crafting_monitor": "无线合成监控器", "item.refinedstorage.creative_wireless_crafting_monitor": "创造无线合成监控器", "item.refinedstorage.quartz_enriched_iron": "富石英铁", "item.refinedstorage.construction_core": "成型核心", "item.refinedstorage.destruction_core": "破坏核心", "item.refinedstorage.silicon": "硅", "item.refinedstorage.basic_processor": "基础处理器", "item.refinedstorage.improved_processor": "进阶处理器", "item.refinedstorage.advanced_processor": "高级处理器", "item.refinedstorage.1k_storage_part": "1k 存储元件", "item.refinedstorage.4k_storage_part": "4k 存储元件", "item.refinedstorage.16k_storage_part": "16k 存储元件", "item.refinedstorage.64k_storage_part": "64k 存储元件", "item.refinedstorage.64k_fluid_storage_part": "64k 流体存储原件", "item.refinedstorage.256k_fluid_storage_part": "256k 流体存储原件", "item.refinedstorage.1024k_fluid_storage_part": "1024k 流体存储原件", "item.refinedstorage.4096k_fluid_storage_part": "4096k 流体存储原件", "item.refinedstorage.pattern": "模板", "item.refinedstorage.upgrade": "空白升级", "item.refinedstorage.range_upgrade": "范围升级", "item.refinedstorage.speed_upgrade": "速度升级", "item.refinedstorage.crafting_upgrade": "合成升级", "item.refinedstorage.stack_upgrade": "堆叠升级", "item.refinedstorage.silk_touch_upgrade": "精准采集升级", "item.refinedstorage.fortune_1_upgrade": "时运升级", "item.refinedstorage.fortune_2_upgrade": "时运升级", "item.refinedstorage.fortune_3_upgrade": "时运升级", "item.refinedstorage.storage_housing": "磁盘外壳", "item.refinedstorage.filter": "过滤升级", "item.refinedstorage.network_card": "网卡", "item.refinedstorage.wrench": "扳手", "item.refinedstorage.security_card": "权限卡", "item.refinedstorage.security_card.owner": "绑定至:%s", "item.refinedstorage.cutting_tool": "切割工具", "item.refinedstorage.cover": "伪装板", "item.refinedstorage.hollow_cover": "空心伪装板", "item.refinedstorage.processor_binding": "处理器粘合物", "commands.refinedstorage.disk.create.error.disk_not_found": "磁盘 %s 未找到.", "commands.refinedstorage.disk.create.success": "成功把磁盘 %s 给了 %s.", "advancements.refinedstorage.controlling.description": "合成了控制器", "advancements.refinedstorage.connecting": "连接", "advancements.refinedstorage.connecting.description": "您可以将所有设备放在一起或者使用【线缆】以将它们连接起来", "advancements.refinedstorage.conditional_connecting": "条件连接", "advancements.refinedstorage.conditional_connecting.description": "制作一个【继电器】来控制网络信号是否可以通过红石", "advancements.refinedstorage.drives": "驱动器", "advancements.refinedstorage.drives.description": "制作【磁盘驱动器】以便能够存储磁盘", "advancements.refinedstorage.manipulating_disks": "磁盘操纵器", "advancements.refinedstorage.manipulating_disks.description": "使用【磁盘操纵器】可以轻松修改磁盘内容", "advancements.refinedstorage.storing_items": "存储物品", "advancements.refinedstorage.storing_items.description": "制作【存储磁盘】并将其放入【磁盘驱动器】中", "advancements.refinedstorage.viewing_items": "浏览物品", "advancements.refinedstorage.viewing_items.description": "制作网格以与您的物品存储进行交互", "advancements.refinedstorage.portable_storage": "便携式存储", "advancements.refinedstorage.portable_storage.description": "制作【便携式网格】,以便在不在网络中的情况下访问磁盘中的项目和流体", "advancements.refinedstorage.upgrading_your_grid": "升级你的网络", "advancements.refinedstorage.upgrading_your_grid.description": "将网络升级到合成网络以获得网络中的制作能力", "advancements.refinedstorage.storing_fluids": "储存液体", "advancements.refinedstorage.storing_fluids.description": "制作一个【流体存储磁盘】并将其放入【磁盘驱动器】中", "advancements.refinedstorage.viewing_fluids": "浏览液体", "advancements.refinedstorage.viewing_fluids.description": "制作网格以与您的液体存储进行交互", "advancements.refinedstorage.better_than_a_barrel": "比桶更好", "advancements.refinedstorage.better_than_a_barrel.description": "制作【存储监视器】以查看,插入或提取网络项", "advancements.refinedstorage.autocrafting": "自动合成", "advancements.refinedstorage.autocrafting.description": "制作一个【装配室】", "advancements.refinedstorage.pattern_creation": "模式创建", "advancements.refinedstorage.pattern_creation.description": "使用模式网络和模式创建模式", "advancements.refinedstorage.monitoring": "监控器!", "advancements.refinedstorage.monitoring.description": "使用【合成监控器】检查制作任务的状态", "advancements.refinedstorage.managing_patterns": "管理模式", "advancements.refinedstorage.managing_patterns.description": "制作【合成管理器】以更好的方式管理您的模式", "advancements.refinedstorage.importing": "输入总线", "advancements.refinedstorage.importing.description": "使用【输入总线】将物品或流体输入存储网络", "advancements.refinedstorage.destruction": "破坏面板", "advancements.refinedstorage.destruction.description": "使用【破坏面板】将块或流体存储到存储网络中", "advancements.refinedstorage.exporting": "输出总线", "advancements.refinedstorage.exporting.description": "使用【输出总线】将物品或流体输出存储网络", "advancements.refinedstorage.construction": "成型面板", "advancements.refinedstorage.construction.description": "使用【成型面板】将物品或流体从存储网络放置出来", "advancements.refinedstorage.security": "安保", "advancements.refinedstorage.security.description": "使用【安全管理器】和【安全卡】保护您的网络", "advancements.refinedstorage.wireless": "无线", "advancements.refinedstorage.wireless.description": "使用【无线发射器】传输网络信号", "advancements.refinedstorage.wireless_items": "无线传输物品", "advancements.refinedstorage.wireless_items.description": "使用【无线终端】以无线方式与您的物品存储进行交互", "advancements.refinedstorage.wireless_fluids": "无线传输液体", "advancements.refinedstorage.wireless_fluids.description": "使用【无线液体终端】以无线方式与您的液体存储进行交互", "advancements.refinedstorage.wireless_monitoring": "无线监控器", "advancements.refinedstorage.wireless_monitoring.description": "使用【无线合成监控器】以无线方式检查制作任务的状态", "advancements.refinedstorage.no_cables_required": "无需电缆", "advancements.refinedstorage.no_cables_required.description": "使用【网络发送器】,【网络接收器】和【网卡】,无需使用电缆即可为网络添加额外组件", "advancements.refinedstorage.upgrading": "升级组件!", "advancements.refinedstorage.upgrading.description": "制作升级组件以改进各种设备", "advancements.refinedstorage.crafting_on_demand": "按需制作", "advancements.refinedstorage.crafting_on_demand.description": "使用【合成升级】在接口、输出总线或成型面板按需合成物品或实体", "advancements.refinedstorage.more_than_just_storage": "不仅仅是存储", "advancements.refinedstorage.more_than_just_storage.description": "将物品,液体,能量和红石从【读取器】转移到【写入器】", "advancements.refinedstorage.detecting": "检测", "advancements.refinedstorage.detecting.description": "使用【检测器】检测网络中的项目或流体", "advancements.refinedstorage.interface_to_the_world": "与世界的接口", "advancements.refinedstorage.interface_to_the_world.description": "使用接口同时导出和导入物品", "advancements.refinedstorage.storing_externally": "外部存储", "advancements.refinedstorage.storing_externally.description": "使用【外部存储总线】为网络提供来自外部实体的存储", "advancements.refinedstorage.covering": "伪装板", "advancements.refinedstorage.covering.description": "合成【伪装板】来隐藏线缆", "advancements.refinedstorage.hollow_covering": "空心伪装板", "advancements.refinedstorage.hollow_covering.description": "合成【空心伪装板】来隐藏线缆并不阻碍线缆穿过", "advancements.refinedstorage.binding": "粘合物", "advancements.refinedstorage.binding.description": "合成【处理器粘合物】来制作各种处理器" } ================================================ FILE: src/main/resources/assets/refinedstorage/lang/zh_tw.json ================================================ { "itemGroup.refinedstorage": "精緻存儲", "itemGroup.refinedstorage.covers": "精緻存儲 偽裝板", "key.refinedstorage.focusSearchBar": "選取終端搜索欄", "key.refinedstorage.clearGridCraftingMatrix": "清除終端合成矩陣", "key.refinedstorage.openWirelessGrid": "開啟無限終端", "key.refinedstorage.openWirelessFluidGrid": "開啟無線液體終端", "key.refinedstorage.openPortableGrid": "開啟便攜終端", "key.refinedstorage.openWirelessCraftingMonitor": "開啟無線合成監控器", "gui.refinedstorage.controller": "控制器", "gui.refinedstorage.creative_controller": "創造控制器", "gui.refinedstorage.grid": "終端", "gui.refinedstorage.grid.craft": "合成", "gui.refinedstorage.crafting_grid": "合成終端", "gui.refinedstorage.pattern_grid": "樣板終端", "gui.refinedstorage.grid.pattern_create": "創造", "gui.refinedstorage.fluid_grid": "液體終端", "gui.refinedstorage.portable_grid": "便攜終端", "gui.refinedstorage.item_amount": "物品數量", "gui.refinedstorage.fluid_amount": "液體數量以mB為單位", "gui.refinedstorage.disk_drive": "磁碟驅動器", "gui.refinedstorage.disk_drive.disks": "磁碟", "gui.refinedstorage.disk_manipulator": "磁碟操縱器", "gui.refinedstorage.disk_manipulator.in": "輸入", "gui.refinedstorage.disk_manipulator.out": "輸出", "gui.refinedstorage.external_storage": "存儲總線", "gui.refinedstorage.importer": "輸入總線", "gui.refinedstorage.exporter": "輸出總線", "gui.refinedstorage.detector": "檢測器", "gui.refinedstorage.destructor": "破壞面板", "gui.refinedstorage.constructor": "成型面板", "gui.refinedstorage.relay": "中繼器", "gui.refinedstorage.interface.import": "輸入端", "gui.refinedstorage.interface.export": "輸出端", "gui.refinedstorage.crafting_monitor": "合成監控器", "gui.refinedstorage.wireless_crafting_monitor": "無線合成監控器", "gui.refinedstorage.crafting_monitor.tooltip.requested": "需要 %d", "gui.refinedstorage.crafting_monitor.stored": "現存: %d", "gui.refinedstorage.crafting_monitor.missing": "缺失: %d", "gui.refinedstorage.crafting_monitor.processing": "處理中: %d", "gui.refinedstorage.crafting_monitor.scheduled": "計劃合成: %d", "gui.refinedstorage.crafting_monitor.crafting": "正在合成: %d", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_item": "機器不接受物品", "gui.refinedstorage.crafting_monitor.machine_does_not_accept_fluid": "機器不接受液體", "gui.refinedstorage.crafting_monitor.machine_none": "沒有找到機器", "gui.refinedstorage.crafting_monitor.crafter_is_locked": "合成被鎖定", "gui.refinedstorage.wireless_transmitter": "無線訪問點", "gui.refinedstorage.wireless_transmitter.distance": "%d 方塊", "gui.refinedstorage.crafter": "裝配室", "gui.refinedstorage.filter": "終端過濾", "gui.refinedstorage.filter.compare_nbt": "NBT", "gui.refinedstorage.filter.mod_filter": "模組過濾", "gui.refinedstorage.network_transmitter": "網路發送器", "gui.refinedstorage.network_transmitter.distance": "%d 方塊", "gui.refinedstorage.network_transmitter.missing_card": "缺失網路卡", "gui.refinedstorage.fluid_interface": "液體接口", "gui.refinedstorage.fluid_interface.in": "輸入", "gui.refinedstorage.fluid_interface.out": "輸出", "gui.refinedstorage.crafting_preview": "合成預覽", "gui.refinedstorage.crafting_preview.to_craft": "合成數量: %d", "gui.refinedstorage.crafting_preview.available": "可用數量: %d", "gui.refinedstorage.crafting_preview.missing": "缺失: %d", "gui.refinedstorage.crafting_preview.error": "請求失敗", "gui.refinedstorage.crafting_preview.error.recursive.0": "其中一種製作成分最終需要", "gui.refinedstorage.crafting_preview.error.recursive.1": "自己.", "gui.refinedstorage.crafting_preview.error.recursive.2": "你需要刪除該模式或確保", "gui.refinedstorage.crafting_preview.error.recursive.3": "在製作過程中不使用模式.", "gui.refinedstorage.crafting_preview.error.recursive.4": "違規模式:", "gui.refinedstorage.crafting_preview.error.too_complex.0": "製作任務計算過於複雜", "gui.refinedstorage.crafting_preview.error.too_complex.1": "並且已停止以緩解伺服器壓力.", "gui.refinedstorage.security_manager": "安全管理器", "gui.refinedstorage.security_manager.configure": "配置", "gui.refinedstorage.security_manager.permission.0": "輸入", "gui.refinedstorage.security_manager.permission.0.tooltip": "輸入物品或液體至網路", "gui.refinedstorage.security_manager.permission.1": "輸出", "gui.refinedstorage.security_manager.permission.1.tooltip": "輸出物品或液體至網路", "gui.refinedstorage.security_manager.permission.2": "自動合成", "gui.refinedstorage.security_manager.permission.2.tooltip": "開始, 取消和瀏覽合成任務", "gui.refinedstorage.security_manager.permission.3": "修改", "gui.refinedstorage.security_manager.permission.3.tooltip": "打開方塊的GUI", "gui.refinedstorage.security_manager.permission.4": "建構", "gui.refinedstorage.security_manager.permission.4.tooltip": "向網路添加或移除設備", "gui.refinedstorage.security_manager.permission.5": "安全", "gui.refinedstorage.security_manager.permission.5.tooltip": "改變安全選項", "gui.refinedstorage.storage_monitor": "存儲監控器", "gui.refinedstorage.crafter_manager": "合成管理器", "gui.refinedstorage.alternatives": "使用替代", "gui.refinedstorage.alternatives.apply": "使用", "misc.refinedstorage.energy_stored": "%d / %d FE", "misc.refinedstorage.energy_usage": "耗能: %d FE/t", "misc.refinedstorage.energy_usage_minimal": "%d FE/t", "misc.refinedstorage.storage.stored": "已存儲: %s", "misc.refinedstorage.storage.stored_capacity": "已存儲: %s / %s", "misc.refinedstorage.storage.stored_minimal": "%s", "misc.refinedstorage.storage.stored_capacity_minimal": "%s / %s", "misc.refinedstorage.storage.full": "%d%% 滿", "misc.refinedstorage.network_item.tooltip": "連接至 %d, %d, %d.", "misc.refinedstorage.network_item.out_of_range": "範圍內沒有無線訪問點.", "misc.refinedstorage.network_item.not_found": "沒有找到網路.", "misc.refinedstorage.network_item.shortcut_not_found": "你的庫存中沒有%s.", "misc.refinedstorage.network_item.shortcut_duplicate": "你的庫存中有多個%s.", "misc.refinedstorage.network_item.out_of_energy": "%s 沒電了.", "misc.refinedstorage.network_card.tooltip": "已在 %s 中連接至 %d, %d, %d.", "misc.refinedstorage.pattern.inputs": "輸入", "misc.refinedstorage.pattern.outputs": "輸出", "misc.refinedstorage.pattern.invalid": "無效樣板", "misc.refinedstorage.pattern.exact": "使用精確模式", "misc.refinedstorage.pattern.allowed_item_tag": "在%s中使用%s的物品", "misc.refinedstorage.pattern.allowed_fluid_tag": "在%s中使用%s的液體", "misc.refinedstorage.pattern.error.processing_no_outputs": "處理中的樣板沒有輸出", "misc.refinedstorage.pattern.error.no_output": "配方沒有輸出", "misc.refinedstorage.pattern.error.recipe_does_not_exist": "配方不存在", "misc.refinedstorage.pattern.error.tag_no_longer_applicable": "標籤%s不再適用於%s", "misc.refinedstorage.security.no_permission": "你沒有權限執行該操作.", "misc.refinedstorage.start": "開始", "misc.refinedstorage.clear": "清除", "misc.refinedstorage.set": "設置", "misc.refinedstorage.cancel_all": "取消所有", "misc.refinedstorage.priority": "優先級", "misc.refinedstorage.exact": "合成模式", "misc.refinedstorage.processing": "熔爐模式", "misc.refinedstorage.total": "總共 %s 個", "misc.refinedstorage.last_modified.just_now": "剛剛被 %s 操作", "misc.refinedstorage.last_modified.second": "%d 秒前被 %s 操作", "misc.refinedstorage.last_modified.seconds": "%d 秒前被 %s 操作", "misc.refinedstorage.last_modified.minute": "%d 分前被 %s 操作", "misc.refinedstorage.last_modified.minutes": "%d 分前被 %s 操作", "misc.refinedstorage.last_modified.hour": "%d 小時前被 %s 操作", "misc.refinedstorage.last_modified.hours": "%d 小時前被 %s 操作", "misc.refinedstorage.last_modified.day": "%d 天前被 %s 操作", "misc.refinedstorage.last_modified.days": "%d 天前被 %s 操作", "misc.refinedstorage.last_modified.week": "%d 月前被 %s 操作", "misc.refinedstorage.last_modified.weeks": "%d 月前被 %s 操作", "misc.refinedstorage.last_modified.year": "%d 年前被 %s 操作", "misc.refinedstorage.last_modified.years": "%d 年前被 %s 操作", "sidebutton.refinedstorage.exact_mode": "精確模式", "sidebutton.refinedstorage.exact_mode.on": "開啟", "sidebutton.refinedstorage.exact_mode.off": "關閉", "sidebutton.refinedstorage.redstone_mode": "紅石模式", "sidebutton.refinedstorage.redstone_mode.0": "忽略紅石信號", "sidebutton.refinedstorage.redstone_mode.1": "有紅石信號時工作", "sidebutton.refinedstorage.redstone_mode.2": "無紅石信號時工作", "sidebutton.refinedstorage.crafter_mode": "合成模式", "sidebutton.refinedstorage.crafter_mode.0": "忽略紅石信號", "sidebutton.refinedstorage.crafter_mode.1": "紅石信號解鎖自動合成", "sidebutton.refinedstorage.crafter_mode.2": "紅石信號鎖定自動合成", "sidebutton.refinedstorage.crafter_mode.3": "紅石脈衝插入下一組", "sidebutton.refinedstorage.grid.view_type": "顯示", "sidebutton.refinedstorage.grid.view_type.0": "普通", "sidebutton.refinedstorage.grid.view_type.1": "隱藏合成", "sidebutton.refinedstorage.grid.view_type.2": "可合成", "sidebutton.refinedstorage.grid.sorting.direction": "排序方式", "sidebutton.refinedstorage.grid.sorting.direction.0": "上升", "sidebutton.refinedstorage.grid.sorting.direction.1": "下降", "sidebutton.refinedstorage.grid.sorting.type": "排序按", "sidebutton.refinedstorage.grid.sorting.type.0": "數量", "sidebutton.refinedstorage.grid.sorting.type.1": "名稱", "sidebutton.refinedstorage.grid.sorting.type.2": "ID", "sidebutton.refinedstorage.grid.sorting.type.3": "InventoryTweaks", "sidebutton.refinedstorage.grid.sorting.type.4": "最後修改", "sidebutton.refinedstorage.grid.search_box_mode": "搜索框模式", "sidebutton.refinedstorage.grid.search_box_mode.0": "標準搜索", "sidebutton.refinedstorage.grid.search_box_mode.1": "自動搜索", "sidebutton.refinedstorage.grid.search_box_mode.2": "JEI標準同步", "sidebutton.refinedstorage.grid.search_box_mode.3": "JEI自動同步", "sidebutton.refinedstorage.grid.size": "大小", "sidebutton.refinedstorage.grid.size.0": "自動", "sidebutton.refinedstorage.grid.size.1": "小", "sidebutton.refinedstorage.grid.size.2": "中", "sidebutton.refinedstorage.grid.size.3": "大", "sidebutton.refinedstorage.mode": "模式", "sidebutton.refinedstorage.mode.whitelist": "白名單", "sidebutton.refinedstorage.mode.blacklist": "黑名單", "sidebutton.refinedstorage.iomode": "IO模式", "sidebutton.refinedstorage.iomode.insert": "輸入到網路", "sidebutton.refinedstorage.iomode.extract": "從網路輸出", "sidebutton.refinedstorage.type": "項目", "sidebutton.refinedstorage.type.0": "物品", "sidebutton.refinedstorage.type.1": "液體", "sidebutton.refinedstorage.detector.mode": "模式", "sidebutton.refinedstorage.detector.mode.0": "物品數量小於輸入數量時輸出信號", "sidebutton.refinedstorage.detector.mode.1": "物品數量等於輸入數量時輸出信號", "sidebutton.refinedstorage.detector.mode.2": "物品數量大於輸入數量時輸出信號", "sidebutton.refinedstorage.constructor.drop": "掉落方塊而不是放置", "sidebutton.refinedstorage.destructor.pickup": "撿起物品而不是破壞", "sidebutton.refinedstorage.access_type": "訪問類型", "sidebutton.refinedstorage.access_type.0": "輸入/輸出", "sidebutton.refinedstorage.access_type.1": "輸入", "sidebutton.refinedstorage.access_type.2": "輸出", "block.refinedstorage.controller": "控制器", "block.refinedstorage.creative_controller": "創造控制器", "block.refinedstorage.cable": "線纜", "block.refinedstorage.grid": "終端", "block.refinedstorage.crafting_grid": "合成終端", "block.refinedstorage.pattern_grid": "樣板終端", "block.refinedstorage.fluid_grid": "液體終端", "block.refinedstorage.disk_drive": "磁碟驅動器", "block.refinedstorage.disk_manipulator": "磁碟操縱器", "block.refinedstorage.external_storage": "存儲總線", "block.refinedstorage.importer": "輸入總線", "block.refinedstorage.exporter": "輸出總線", "block.refinedstorage.detector": "檢測器", "block.refinedstorage.machine_casing": "機械框架", "block.refinedstorage.destructor": "破壞面板", "block.refinedstorage.constructor": "成型面板", "block.refinedstorage.1k_storage_block": "1k 存儲方塊", "block.refinedstorage.4k_storage_block": "4k 存儲方塊", "block.refinedstorage.16k_storage_block": "16k 存儲方塊", "block.refinedstorage.64k_storage_block": "64k 存儲方塊", "block.refinedstorage.creative_storage_block": "創造存儲方塊", "block.refinedstorage.relay": "中繼器", "block.refinedstorage.interface": "接口", "block.refinedstorage.crafting_monitor": "合成監控器", "block.refinedstorage.wireless_transmitter": "無線訪問點", "block.refinedstorage.wireless_transmitter.tooltip": "必須放置在 %s 上.", "block.refinedstorage.crafter": "裝配室", "block.refinedstorage.network_receiver": "網路接收器", "block.refinedstorage.network_transmitter": "網路發送器", "block.refinedstorage.fluid_interface": "液體接口", "block.refinedstorage.64k_fluid_storage_block": "64k 液體存儲方塊", "block.refinedstorage.256k_fluid_storage_block": "256k 液體存儲方塊", "block.refinedstorage.1024k_fluid_storage_block": "1024k 液體存儲方塊", "block.refinedstorage.4096k_fluid_storage_block": "4096k 液體存儲方塊", "block.refinedstorage.creative_fluid_storage_block": "創造液體存儲方塊", "block.refinedstorage.security_manager": "安全管理器", "block.refinedstorage.quartz_enriched_iron_block": "石英富鐵磚", "block.refinedstorage.storage_monitor": "存儲監控器", "block.refinedstorage.portable_grid": "便攜終端", "block.refinedstorage.creative_portable_grid": "創造便攜終端", "block.refinedstorage.portable_grid.tooltip": "Shift進行放置.", "block.refinedstorage.crafter_manager": "合成管理器", "item.refinedstorage.1k_storage_disk": "1k 存儲磁碟", "item.refinedstorage.4k_storage_disk": "4k 存儲磁碟", "item.refinedstorage.16k_storage_disk": "16k 存儲磁碟", "item.refinedstorage.64k_storage_disk": "64k 存儲磁碟", "item.refinedstorage.creative_storage_disk": "創造存儲磁碟", "item.refinedstorage.64k_fluid_storage_disk": "64k 液體存儲磁碟", "item.refinedstorage.256k_fluid_storage_disk": "256k 液體存儲磁碟", "item.refinedstorage.1024k_fluid_storage_disk": "1024k 液體存儲磁碟", "item.refinedstorage.4096k_fluid_storage_disk": "4096k 液體存儲磁碟", "item.refinedstorage.creative_fluid_storage_disk": "創造液體存儲磁碟", "item.refinedstorage.wireless_grid": "無線終端", "item.refinedstorage.creative_wireless_grid": "創造無線終端", "item.refinedstorage.wireless_fluid_grid": "無線液體終端", "item.refinedstorage.creative_wireless_fluid_grid": "創造無線液體終端", "item.refinedstorage.wireless_crafting_monitor": "無線合成監控器", "item.refinedstorage.creative_wireless_crafting_monitor": "創造無線合成監控器", "item.refinedstorage.quartz_enriched_iron": "石英富鐵", "item.refinedstorage.construction_core": "成型核心", "item.refinedstorage.destruction_core": "破壞核心", "item.refinedstorage.silicon": "矽", "item.refinedstorage.raw_basic_processor": "未處理的基礎處理器", "item.refinedstorage.raw_improved_processor": "未處理的進階處理器", "item.refinedstorage.raw_advanced_processor": "未處理的高級處理器", "item.refinedstorage.basic_processor": "基礎處理器", "item.refinedstorage.improved_processor": "進階處理器", "item.refinedstorage.advanced_processor": "高級處理器", "item.refinedstorage.1k_storage_part": "1k 存儲元件", "item.refinedstorage.4k_storage_part": "4k 存儲元件", "item.refinedstorage.16k_storage_part": "16k 存儲元件", "item.refinedstorage.64k_storage_part": "64k 存儲元件", "item.refinedstorage.64k_fluid_storage_part": "64k 液體存儲元件", "item.refinedstorage.256k_fluid_storage_part": "256k 液體存儲元件", "item.refinedstorage.1024k_fluid_storage_part": "1024k 液體存儲元件", "item.refinedstorage.4096k_fluid_storage_part": "4096k 液體存儲元件", "item.refinedstorage.pattern": "樣板", "item.refinedstorage.upgrade": "升級", "item.refinedstorage.range_upgrade": "範圍升級", "item.refinedstorage.speed_upgrade": "速度升級", "item.refinedstorage.crafting_upgrade": "合成升級", "item.refinedstorage.stack_upgrade": "堆疊升級", "item.refinedstorage.silk_touch_upgrade": "絲綢之觸升級", "item.refinedstorage.fortune_1_upgrade": "幸運升級", "item.refinedstorage.fortune_2_upgrade": "幸運升級", "item.refinedstorage.fortune_3_upgrade": "幸運升級", "item.refinedstorage.regulator_upgrade": "調節升級", "item.refinedstorage.storage_housing": "存儲外殼", "item.refinedstorage.filter": "過濾器", "item.refinedstorage.network_card": "網路卡", "item.refinedstorage.wrench": "板手", "item.refinedstorage.security_card": "安全卡", "item.refinedstorage.security_card.owner": "綁定至: %s", "item.refinedstorage.processor_binding": "處理器黏合物", "commands.refinedstorage.disk.create.error.disk_not_found": "磁碟 %s 未找到.", "commands.refinedstorage.disk.create.success": "成功把磁碟 %s 給了 %s.", "advancements.refinedstorage.controlling.description": "合成一個控制器", "advancements.refinedstorage.connecting": "連接", "advancements.refinedstorage.connecting.description": "你可以將所有設備放在一起或者使用線纜以將它們連接起來", "advancements.refinedstorage.conditional_connecting": "條件連接", "advancements.refinedstorage.conditional_connecting.description": "製作一個中繼器來控制網路信號是否可以通過紅石", "advancements.refinedstorage.drives": "驅動器", "advancements.refinedstorage.drives.description": "製作磁碟驅動器以便能夠存儲磁碟", "advancements.refinedstorage.manipulating_disks": "磁碟操縱器", "advancements.refinedstorage.manipulating_disks.description": "使用磁碟操縱器可以輕鬆修改磁碟內容", "advancements.refinedstorage.storing_items": "存儲物品", "advancements.refinedstorage.storing_items.description": "製作存儲磁碟並將其放入磁碟驅動器中", "advancements.refinedstorage.viewing_items": "瀏覽物品", "advancements.refinedstorage.viewing_items.description": "製作終端與你的物品存儲進行交互", "advancements.refinedstorage.portable_storage": "便攜存儲", "advancements.refinedstorage.portable_storage.description": "製作便攜式終端,以便在不在網路中的情況下訪問磁碟中的物品或液體", "advancements.refinedstorage.upgrading_your_grid": "升級你的終端", "advancements.refinedstorage.upgrading_your_grid.description": "將終端升級到合成終端以獲得終端中的製作能力", "advancements.refinedstorage.storing_fluids": "存儲液體", "advancements.refinedstorage.storing_fluids.description": "製作液體存儲磁碟並將其放入磁碟驅動器中", "advancements.refinedstorage.viewing_fluids": "瀏覽液體", "advancements.refinedstorage.viewing_fluids.description": "製作液體終端與你的液體存儲進行交互", "advancements.refinedstorage.better_than_a_barrel": "比桶更好", "advancements.refinedstorage.better_than_a_barrel.description": "製作存儲監控器以查看,網路中物品的輸入或輸出", "advancements.refinedstorage.autocrafting": "合成自動化", "advancements.refinedstorage.autocrafting.description": "製作一個裝配室", "advancements.refinedstorage.pattern_creation": "編寫樣板", "advancements.refinedstorage.pattern_creation.description": "使用樣板終端和樣板編寫樣板", "advancements.refinedstorage.monitoring": "監控器", "advancements.refinedstorage.monitoring.description": "使用合成監控器檢查製作任務的狀態", "advancements.refinedstorage.managing_patterns": "樣板管理器", "advancements.refinedstorage.managing_patterns.description": "製作樣板管理器以更好的方式管理你的樣板", "advancements.refinedstorage.importing": "輸入總線", "advancements.refinedstorage.importing.description": "使用輸入總線將物品或流體輸入存儲網路", "advancements.refinedstorage.destruction": "破壞面板", "advancements.refinedstorage.destruction.description": "使用破壞面板將物品或流體輸出存儲網路", "advancements.refinedstorage.exporting": "輸出總線", "advancements.refinedstorage.exporting.description": "使用輸出總線將物品或流體輸出存儲網路", "advancements.refinedstorage.construction": "成型面板", "advancements.refinedstorage.construction.description": "使用成型面板將物品或流體輸出存儲網路", "advancements.refinedstorage.security": "安全", "advancements.refinedstorage.security.description": "使用安全管理器和安全卡保護你的網路", "advancements.refinedstorage.wireless": "無線", "advancements.refinedstorage.wireless.description": "使用無線訪問點傳輸網路信號", "advancements.refinedstorage.wireless_items": "無線物品", "advancements.refinedstorage.wireless_items.description": "使用無線終端以無線方式與你的物品存儲進行交互", "advancements.refinedstorage.wireless_fluids": "無線液體", "advancements.refinedstorage.wireless_fluids.description": "使用無線終端以無線方式與你的液體存儲進行交互", "advancements.refinedstorage.wireless_monitoring": "無線監控器", "advancements.refinedstorage.wireless_monitoring.description": "使用無線合成監控器以無線方式檢查製作任務的狀態", "advancements.refinedstorage.no_cables_required": "無需線纜", "advancements.refinedstorage.no_cables_required.description": "使用網路發送器,網路接收器和網路卡,無需使用線纜即可為網路添加額外組件", "advancements.refinedstorage.upgrading": "升級組件", "advancements.refinedstorage.upgrading.description": "製作升級組件以改進各種設備", "advancements.refinedstorage.crafting_on_demand": "按照需求合成", "advancements.refinedstorage.crafting_on_demand.description": "使用合成升級在接口、輸出總線或成型面板按照需求合成物品或方塊", "advancements.refinedstorage.detecting": "檢測器", "advancements.refinedstorage.detecting.description": "使用檢測器檢測網路中的物品或液體", "advancements.refinedstorage.interface_to_the_world": "與世界的接口", "advancements.refinedstorage.interface_to_the_world.description": "使用接口同時輸出和輸入物品", "advancements.refinedstorage.storing_externally": "存儲總線", "advancements.refinedstorage.storing_externally.description": "使用存儲總線總線為網路提供來自外部實體的存儲" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/1024k_fluid_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/1024k_fluid_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/16k_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/16k_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/1k_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/1k_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/256k_fluid_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/256k_fluid_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/4096k_fluid_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/4096k_fluid_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/4k_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/4k_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/64k_fluid_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/64k_fluid_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/64k_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/64k_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cable_core.json ================================================ { "render_type": "cutout", "textures": { "cable": "refinedstorage:block/cable", "particle": "refinedstorage:block/cable" }, "elements": [ { "name": "Core", "from": [ 6.0, 6.0, 6.0 ], "to": [ 10.0, 10.0, 10.0 ], "faces": { "north": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "east": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "south": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "west": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "up": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "down": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cable_extension.json ================================================ { "render_type": "cutout", "textures": { "cable": "refinedstorage:block/cable", "particle": "refinedstorage:block/cable" }, "elements": [ { "name": "North", "from": [ 6.0, 6.0, 0.0 ], "to": [ 10.0, 10.0, 6.0 ], "faces": { "north": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "east": { "texture": "#cable", "uv": [ 10.0, 6.0, 16.0, 10.0 ] }, "south": { "texture": "#cable", "uv": [ 6.0, 6.0, 10.0, 10.0 ] }, "west": { "texture": "#cable", "uv": [ 0.0, 6.0, 6.0, 10.0 ] }, "up": { "texture": "#cable", "uv": [ 6.0, 0.0, 10.0, 6.0 ] }, "down": { "texture": "#cable", "uv": [ 6.0, 10.0, 10.0, 16.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/constructor_connected.json ================================================ { "parent": "refinedstorage:block/constructor_destructor", "textures": { "front": "refinedstorage:block/constructor/constructor", "cutout": "refinedstorage:block/constructor/cutouts/connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/constructor_destructor.json ================================================ { "render_type": "cutout", "textures": { "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#front", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "east": { "texture": "#border", "uv": [ 14.0, 0.0, 16.0, 16.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 16.0 ] }, "up": { "texture": "#border", "uv": [ 2.0, 0.0, 14.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 2.0, 14.0, 14.0, 16.0 ] } } }, { "name": "Line3", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#cutout", "uv": [ 0.0, 0.0, 16.0, 16.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/constructor_destructor_nonemissive.json ================================================ { "render_type": "cutout", "textures": { "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#front", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "east": { "texture": "#border", "uv": [ 14.0, 0.0, 16.0, 16.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 16.0 ] }, "up": { "texture": "#border", "uv": [ 2.0, 0.0, 14.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 2.0, 14.0, 14.0, 16.0 ] } } }, { "name": "Line3", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#cutout", "uv": [ 0.0, 0.0, 16.0, 16.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/constructor_disconnected.json ================================================ { "parent": "refinedstorage:block/constructor_destructor_nonemissive", "textures": { "front": "refinedstorage:block/constructor/constructor", "cutout": "refinedstorage:block/constructor/cutouts/disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/controller_nearly.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#all", "cullface": "down" }, "up": { "texture": "#all", "cullface": "up" }, "north": { "texture": "#all", "cullface": "north" }, "south": { "texture": "#all", "cullface": "south" }, "west": { "texture": "#all", "cullface": "west" }, "east": { "texture": "#all", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout", "cullface": "up" }, "down": { "texture": "#cutout", "cullface": "down" }, "north": { "texture": "#cutout", "cullface": "north" }, "south": { "texture": "#cutout", "cullface": "south" }, "west": { "texture": "#cutout", "cullface": "west" }, "east": { "texture": "#cutout", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout_gray", "cullface": "up" }, "down": { "texture": "#cutout_gray", "cullface": "down" }, "north": { "texture": "#cutout_gray", "cullface": "north" }, "south": { "texture": "#cutout_gray", "cullface": "south" }, "west": { "texture": "#cutout_gray", "cullface": "west" }, "east": { "texture": "#cutout_gray", "cullface": "east" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/creative_fluid_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/creative_fluid_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/creative_storage_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/creative_storage_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_all_cutout.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#all", "cullface": "down" }, "up": { "texture": "#all", "cullface": "up" }, "north": { "texture": "#all", "cullface": "north" }, "south": { "texture": "#all", "cullface": "south" }, "west": { "texture": "#all", "cullface": "west" }, "east": { "texture": "#all", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout", "cullface": "up", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "texture": "#cutout", "cullface": "down", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "north": { "texture": "#cutout", "cullface": "north", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "texture": "#cutout", "cullface": "south", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "texture": "#cutout", "cullface": "west", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "texture": "#cutout", "cullface": "east", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_all_cutout_nonemissive.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#all", "cullface": "down" }, "up": { "texture": "#all", "cullface": "up" }, "north": { "texture": "#all", "cullface": "north" }, "south": { "texture": "#all", "cullface": "south" }, "west": { "texture": "#all", "cullface": "west" }, "east": { "texture": "#all", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout", "cullface": "up" }, "down": { "texture": "#cutout", "cullface": "down" }, "north": { "texture": "#cutout", "cullface": "north" }, "south": { "texture": "#cutout", "cullface": "south" }, "west": { "texture": "#cutout", "cullface": "west" }, "east": { "texture": "#cutout", "cullface": "east" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_cutout.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#down", "cullface": "down" }, "up": { "texture": "#up", "cullface": "up" }, "north": { "texture": "#north", "cullface": "north" }, "south": { "texture": "#south", "cullface": "south" }, "west": { "texture": "#west", "cullface": "west" }, "east": { "texture": "#east", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout_up", "cullface": "up", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "texture": "#cutout_down", "cullface": "down", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "north": { "texture": "#cutout_north", "cullface": "north", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "texture": "#cutout_south", "cullface": "south", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "texture": "#cutout_west", "cullface": "west", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "texture": "#cutout_east", "cullface": "east", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_cutout_nonemissive.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#down", "cullface": "down" }, "up": { "texture": "#up", "cullface": "up" }, "north": { "texture": "#north", "cullface": "north" }, "south": { "texture": "#south", "cullface": "south" }, "west": { "texture": "#west", "cullface": "west" }, "east": { "texture": "#east", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "up": { "texture": "#cutout_up", "cullface": "up" }, "down": { "texture": "#cutout_down", "cullface": "down" }, "north": { "texture": "#cutout_north", "cullface": "north" }, "south": { "texture": "#cutout_south", "cullface": "south" }, "west": { "texture": "#cutout_west", "cullface": "west" }, "east": { "texture": "#cutout_east", "cullface": "east" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_north_cutout.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#down", "cullface": "down" }, "up": { "texture": "#up", "cullface": "up" }, "north": { "texture": "#north", "cullface": "north" }, "south": { "texture": "#south", "cullface": "south" }, "west": { "texture": "#west", "cullface": "west" }, "east": { "texture": "#east", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "north": { "texture": "#cutout", "cullface": "north", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/cube_north_cutout_nonemissive.json ================================================ { "render_type": "cutout", "parent": "block/cube", "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#down", "cullface": "down" }, "up": { "texture": "#up", "cullface": "up" }, "north": { "texture": "#north", "cullface": "north" }, "south": { "texture": "#south", "cullface": "south" }, "west": { "texture": "#west", "cullface": "west" }, "east": { "texture": "#east", "cullface": "east" } } }, { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "north": { "texture": "#cutout", "cullface": "north" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/destructor_connected.json ================================================ { "parent": "refinedstorage:block/constructor_destructor", "textures": { "front": "refinedstorage:block/destructor/destructor", "cutout": "refinedstorage:block/destructor/cutouts/connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/destructor_disconnected.json ================================================ { "parent": "refinedstorage:block/constructor_destructor_nonemissive", "textures": { "front": "refinedstorage:block/destructor/destructor", "cutout": "refinedstorage:block/destructor/cutouts/disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/detector.json ================================================ { "render_type": "cutout", "parent": "block/cube", "textures": { "side": "refinedstorage:block/detector/side", "bottom": "refinedstorage:block/detector/bottom", "top": "refinedstorage:block/detector/top", "particle": "refinedstorage:block/detector/side" }, "elements": [ { "name": "Handle", "from": [ 7, 5, 7 ], "to": [ 9, 8, 9 ], "shade": false, "faces": { "north": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "east": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "south": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "west": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "up": { "uv": [ 7, 7, 9, 9 ], "texture": "#side" } } }, { "name": "Torch", "from": [ 7, 5, 6 ], "to": [ 9, 11, 10 ], "shade": false, "faces": { "east": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } }, { "name": "Torch", "from": [ 6, 5, 7 ], "to": [ 10, 11, 9 ], "shade": false, "faces": { "north": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } }, { "name": "Base", "from": [ 0, 0, 0 ], "to": [ 16, 5, 16 ], "faces": { "north": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "east": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "south": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "west": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/detector_nonemissive.json ================================================ { "render_type": "cutout", "parent": "block/cube", "textures": { "side": "refinedstorage:block/detector/side", "bottom": "refinedstorage:block/detector/bottom", "top": "refinedstorage:block/detector/top", "particle": "refinedstorage:block/detector/side" }, "elements": [ { "name": "Handle", "from": [ 7, 5, 7 ], "to": [ 9, 8, 9 ], "shade": false, "faces": { "north": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "east": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "south": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "west": { "uv": [ 7, 7, 9, 11 ], "texture": "#side" }, "up": { "uv": [ 7, 7, 9, 9 ], "texture": "#side" } } }, { "name": "Torch", "from": [ 7, 5, 6 ], "to": [ 9, 11, 10 ], "shade": false, "faces": { "east": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch" }, "west": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch" } } }, { "name": "Torch", "from": [ 6, 5, 7 ], "to": [ 10, 11, 9 ], "shade": false, "faces": { "north": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch" }, "south": { "uv": [ 6, 4, 10, 12 ], "texture": "#torch" } } }, { "name": "Base", "from": [ 0, 0, 0 ], "to": [ 16, 5, 16 ], "faces": { "north": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "east": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "south": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "west": { "uv": [ 0, 11, 16, 16 ], "texture": "#side" }, "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#top" }, "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#bottom" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disk_drive.json ================================================ { "loader": "refinedstorage:disk_drive" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disk_drive_base.json ================================================ { "parent": "block/block", "textures": { "particle": "refinedstorage:block/disk_drive", "front": "refinedstorage:block/disk_drive", "bottom": "refinedstorage:block/disk_drive_bottom", "top": "refinedstorage:block/disk_drive_top", "side": "refinedstorage:block/disk_drive_side" }, "elements": [ { "from": [ 0, 0, 0 ], "to": [ 16, 16, 16 ], "faces": { "down": { "texture": "#bottom", "cullface": "down" }, "up": { "texture": "#top", "cullface": "up" }, "north": { "texture": "#front", "cullface": "north" }, "south": { "texture": "#side", "cullface": "south" }, "west": { "texture": "#side", "cullface": "west" }, "east": { "texture": "#side", "cullface": "east" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/disk.json ================================================ { "textures": { "base": "refinedstorage:block/disks/disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ 11.0, 14.0, -1.0 ], "to": [ 16.0, 16.0, 0.0 ], "faces": { "north": { "texture": "#base", "uv": [ 3.0, 0.0, 8.0, 2.0 ] }, "east": { "texture": "#base", "uv": [ 2.0, 0.0, 3.0, 2.0 ] }, "south": { "texture": "#base", "uv": [ 9.0, 0.0, 14.0, 2.0 ] }, "west": { "texture": "#base", "uv": [ 8.0, 0.0, 9.0, 2.0 ] }, "up": { "texture": "#base", "uv": [ 3.0, 2.0, 8.0, 3.0 ] }, "down": { "texture": "#base", "uv": [ 3.0, 3.0, 8.0, 4.0 ] } } }, { "name": "led", "from": [ 12.0, 13.95, -1.05 ], "to": [ 13.0, 15.0, -0.10000000000000009 ], "faces": { "north": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "texture": "#led", "uv": [ 2.0, 0.0, 3.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/disk_disconnected.json ================================================ { "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", "textures": { "base": "refinedstorage:block/disks/disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ 11.0, 14.0, -1.0 ], "to": [ 16.0, 16.0, 0.0 ], "faces": { "north": { "texture": "#base", "uv": [ 3.0, 0.0, 8.0, 2.0 ] }, "east": { "texture": "#base", "uv": [ 2.0, 0.0, 3.0, 2.0 ] }, "south": { "texture": "#base", "uv": [ 9.0, 0.0, 14.0, 2.0 ] }, "west": { "texture": "#base", "uv": [ 8.0, 0.0, 9.0, 2.0 ] }, "up": { "texture": "#base", "uv": [ 3.0, 2.0, 8.0, 3.0 ] }, "down": { "texture": "#base", "uv": [ 3.0, 3.0, 8.0, 4.0 ] } } }, { "name": "led", "from": [ 12.0, 13.95, -1.05 ], "to": [ 13.0, 15.0, -0.10000000000000009 ], "faces": { "north": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] }, "east": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] }, "south": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] }, "west": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] }, "up": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] }, "down": { "texture": "#led", "uv": [ 3.0, 0.0, 4.0, 1.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/disk_full.json ================================================ { "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", "textures": { "base": "refinedstorage:block/disks/disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ 11.0, 14.0, -1.0 ], "to": [ 16.0, 16.0, 0.0 ], "faces": { "north": { "texture": "#base", "uv": [ 3.0, 0.0, 8.0, 2.0 ] }, "east": { "texture": "#base", "uv": [ 2.0, 0.0, 3.0, 2.0 ] }, "south": { "texture": "#base", "uv": [ 9.0, 0.0, 14.0, 2.0 ] }, "west": { "texture": "#base", "uv": [ 8.0, 0.0, 9.0, 2.0 ] }, "up": { "texture": "#base", "uv": [ 3.0, 2.0, 8.0, 3.0 ] }, "down": { "texture": "#base", "uv": [ 3.0, 3.0, 8.0, 4.0 ] } } }, { "name": "led", "from": [ 12.0, 13.95, -1.05 ], "to": [ 13.0, 15.0, -0.10000000000000009 ], "faces": { "north": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "texture": "#led", "uv": [ 1.0, 0.0, 2.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/disk_near_capacity.json ================================================ { "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", "textures": { "base": "refinedstorage:block/disks/disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ 11.0, 14.0, -1.0 ], "to": [ 16.0, 16.0, 0.0 ], "faces": { "north": { "texture": "#base", "uv": [ 3.0, 0.0, 8.0, 2.0 ] }, "east": { "texture": "#base", "uv": [ 2.0, 0.0, 3.0, 2.0 ] }, "south": { "texture": "#base", "uv": [ 9.0, 0.0, 14.0, 2.0 ] }, "west": { "texture": "#base", "uv": [ 8.0, 0.0, 9.0, 2.0 ] }, "up": { "texture": "#base", "uv": [ 3.0, 2.0, 8.0, 3.0 ] }, "down": { "texture": "#base", "uv": [ 3.0, 3.0, 8.0, 4.0 ] } } }, { "name": "led", "from": [ 12.0, 13.95, -1.05 ], "to": [ 13.0, 15.0, -0.10000000000000009 ], "faces": { "north": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "texture": "#led", "uv": [ 0.0, 0.0, 1.0, 1.0 ], "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk.json ================================================ { "textures": { "disk": "refinedstorage:block/disks/portable_grid_disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ -1, 2, 9 ], "to": [ 0, 4, 14 ], "shade": true, "faces": { "north": { "uv": [ 5, 5, 6, 7 ], "texture": "#disk" }, "east": { "uv": [ 0, 5, 5, 7 ], "texture": "#disk" }, "south": { "uv": [ 11, 5, 12, 7 ], "texture": "#disk" }, "west": { "uv": [ 6, 5, 11, 7 ], "texture": "#disk" }, "up": { "uv": [ 5, 0, 6, 5 ], "texture": "#disk", "rotation": 180 }, "down": { "uv": [ 6, 0, 7, 5 ], "texture": "#disk", "rotation": 180 } } }, { "name": "disk_led", "from": [ -1.05, 2, 12 ], "to": [ -0.050000000000000044, 3, 13 ], "shade": true, "faces": { "east": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "north": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "uv": [ 2, 0, 3, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_disconnected.json ================================================ { "textures": { "disk": "refinedstorage:block/disks/portable_grid_disk", "led": "refinedstorage:block/disks/portable_grid_leds" }, "elements": [ { "name": "disk", "from": [ -1, 2, 9 ], "to": [ 0, 4, 14 ], "shade": true, "faces": { "north": { "uv": [ 5, 5, 6, 7 ], "texture": "#disk" }, "east": { "uv": [ 0, 5, 5, 7 ], "texture": "#disk" }, "south": { "uv": [ 11, 5, 12, 7 ], "texture": "#disk" }, "west": { "uv": [ 6, 5, 11, 7 ], "texture": "#disk" }, "up": { "uv": [ 5, 0, 6, 5 ], "texture": "#disk", "rotation": 180 }, "down": { "uv": [ 6, 0, 7, 5 ], "texture": "#disk", "rotation": 180 } } }, { "name": "disk_led", "from": [ -1.05, 2, 12 ], "to": [ -0.050000000000000044, 3, 13 ], "shade": true, "faces": { "east": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" }, "west": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" }, "north": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" }, "south": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" }, "up": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" }, "down": { "uv": [ 3, 0, 4, 1 ], "texture": "#led" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_full.json ================================================ { "textures": { "disk": "refinedstorage:block/disks/portable_grid_disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ -1, 2, 9 ], "to": [ 0, 4, 14 ], "shade": true, "faces": { "north": { "uv": [ 5, 5, 6, 7 ], "texture": "#disk" }, "east": { "uv": [ 0, 5, 5, 7 ], "texture": "#disk" }, "south": { "uv": [ 11, 5, 12, 7 ], "texture": "#disk" }, "west": { "uv": [ 6, 5, 11, 7 ], "texture": "#disk" }, "up": { "uv": [ 5, 0, 6, 5 ], "texture": "#disk", "rotation": 180 }, "down": { "uv": [ 6, 0, 7, 5 ], "texture": "#disk", "rotation": 180 } } }, { "name": "disk_led", "from": [ -1.05, 2, 12 ], "to": [ -0.050000000000000044, 3, 13 ], "shade": true, "faces": { "east": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "north": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "uv": [ 1, 0, 2, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/disks/portable_grid_disk_near_capacity.json ================================================ { "textures": { "disk": "refinedstorage:block/disks/portable_grid_disk", "led": "refinedstorage:block/disks/leds" }, "elements": [ { "name": "disk", "from": [ -1, 2, 9 ], "to": [ 0, 4, 14 ], "shade": true, "faces": { "north": { "uv": [ 5, 5, 6, 7 ], "texture": "#disk" }, "east": { "uv": [ 0, 5, 5, 7 ], "texture": "#disk" }, "south": { "uv": [ 11, 5, 12, 7 ], "texture": "#disk" }, "west": { "uv": [ 6, 5, 11, 7 ], "texture": "#disk" }, "up": { "uv": [ 5, 0, 6, 5 ], "texture": "#disk", "rotation": 180 }, "down": { "uv": [ 6, 0, 7, 5 ], "texture": "#disk", "rotation": 180 } } }, { "name": "disk_led", "from": [ -1.05, 2, 12 ], "to": [ -0.050000000000000044, 3, 13 ], "shade": true, "faces": { "east": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "west": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "north": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "down": { "uv": [ 0, 0, 1, 1 ], "texture": "#led", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/exporter.json ================================================ { "render_type": "cutout", "textures": { "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Line1", "from": [ 6, 6, 0 ], "to": [ 10, 10, 2 ], "faces": { "north": { "uv": [ 0, 0, 4, 4 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 4 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 4, 4 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 4 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 4, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 4, 2 ], "texture": "#border" } } }, { "name": "Line2", "from": [ 5, 5, 2 ], "to": [ 11, 11, 4 ], "faces": { "north": { "uv": [ 0, 0, 6, 6 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 6 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 6, 6 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 6 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 6, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 6, 2 ], "texture": "#border" } } }, { "name": "Line3", "from": [ 3, 3, 4 ], "to": [ 13, 13, 6 ], "faces": { "north": { "uv": [ 0, 0, 10, 10 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 10 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 10, 10 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 10 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 10, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 10, 2 ], "texture": "#border" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/external_storage.json ================================================ { "render_type": "cutout", "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", "textures": { "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 3.0, 3.0, 0.0 ], "to": [ 13.0, 13.0, 2.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/fluid_interface_connected.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/fluid_interface_connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/fluid_interface_disconnected.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/fluid_interface_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/importer.json ================================================ { "render_type": "cutout", "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", "textures": { "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Line1", "from": [ 6.0, 6.0, 4.0 ], "to": [ 10.0, 10.0, 6.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] } } }, { "name": "Line2", "from": [ 5.0, 5.0, 2.0 ], "to": [ 11.0, 11.0, 4.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 6.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 6.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 6.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 6.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 2.0 ] } } }, { "name": "Line3", "from": [ 3.0, 3.0, 0.0 ], "to": [ 13.0, 13.0, 2.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/interface_connected.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/interface_connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/interface_disconnected.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/interface_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/machine_casing.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/machine_casing" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/portable_grid.json ================================================ { "render_type": "cutout", "loader": "refinedstorage:portable_grid" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/portable_grid_base.json ================================================ { "render_type": "cutout", "parent": "block/cube", "textures": { "particle": "refinedstorage:block/portable_grid_1", "texture0": "refinedstorage:block/portable_grid_1", "texture2": "refinedstorage:block/portable_grid_3", "texture3": "refinedstorage:block/portable_grid_4", "texture4": "refinedstorage:block/portable_grid_5", "texture5": "refinedstorage:block/portable_grid_6", "texture6": "refinedstorage:block/portable_grid_7", "texture7": "refinedstorage:block/portable_grid_8" }, "display": { "firstperson_lefthand": { "rotation": [10, 130, 0], "scale": [0.4, 0.4, 0.4], "translation": [2, 3.5, 0] }, "firstperson_righthand": { "rotation": [10, 130, 0], "scale": [0.4, 0.4, 0.4], "translation": [2, 3.5, 0] }, "thirdperson_lefthand": { "rotation": [10, 180, 0], "scale": [0.4, 0.4, 0.4], "translation": [0, 3, 1] }, "thirdperson_righthand": { "rotation": [10, 180, 0], "scale": [0.4, 0.4, 0.4], "translation": [0, 3, 1] }, "gui": { "rotation": [30, 225, 0], "scale": [0.625, 0.625, 0.625] }, "ground": { "translation": [0, 3, 0], "scale": [0.25, 0.25, 0.25] }, "fixed": { "scale": [0.75, 0.75, 0.75] } }, "elements": [ { "name": "cube", "from": [ 0, 6, 5 ], "to": [ 16, 13, 7 ], "shade": true, "faces": { "north": { "uv": [ 0, 7, 16, 14 ], "texture": "#texture0" }, "east": { "uv": [ 0, 7, 2, 14 ], "texture": "#texture1" }, "south": { "uv": [ 0, 0, 16, 7 ], "texture": "#texture0" }, "west": { "uv": [ 0, 0, 2, 7 ], "texture": "#texture1" }, "up": { "uv": [ 0, 0, 16, 2 ], "texture": "#texture0", "rotation": 180 }, "down": { "uv": [ 0, 13, 16, 15 ], "texture": "#texture1", "rotation": 180 } }, "rotation": { "origin": [ 8, 6, 7 ], "axis": "x", "angle": 22.5 } }, { "name": "cube", "from": [ 0, 4, 7 ], "to": [ 16, 6, 16 ], "shade": true, "faces": { "north": { "uv": [ 0, 14, 16, 16 ], "texture": "#texture0" }, "east": { "uv": [ 3, 2, 12, 4 ], "texture": "#texture1" }, "south": { "uv": [ 0, 0, 16, 2 ], "texture": "#texture2" }, "west": { "uv": [ 3, 0, 12, 2 ], "texture": "#texture1" }, "up": { "uv": [ 0, 2, 16, 11 ], "texture": "#texture2", "rotation": 180 }, "down": { "uv": [ 0, 0, 16, 9 ], "texture": "#texture3", "rotation": 180 } } }, { "name": "cube", "from": [ 0, 0, 0 ], "to": [ 16, 4, 16 ], "shade": true, "faces": { "north": { "uv": [ 0, 9, 16, 13 ], "texture": "#texture3" }, "east": { "uv": [ 0, 4, 16, 8 ], "texture": "#texture4" }, "south": { "uv": [ 0, 11, 16, 15 ], "texture": "#texture2" }, "west": { "uv": [ 0, 0, 16, 4 ], "texture": "#texture4" }, "up": { "uv": [ 0, 0, 16, 16 ], "texture": "#texture5", "rotation": 180 }, "down": { "uv": [ 0, 0, 16, 16 ], "texture": "#texture6", "rotation": 180 } } }, { "name": "cube", "from": [ 1, 4, 1 ], "to": [ 15, 5, 7 ], "shade": true, "faces": { "north": { "uv": [ 0, 15, 14, 16 ], "texture": "#texture2" }, "east": { "uv": [ 4, 9, 10, 10 ], "texture": "#texture1" }, "south": { "uv": [ 2, 13, 16, 14 ], "texture": "#texture1" }, "west": { "uv": [ 4, 8, 10, 9 ], "texture": "#texture1" }, "up": { "uv": [ 0, 8, 14, 14 ], "texture": "#texture4", "rotation": 180 }, "down": { "uv": [ 0, 0, 14, 6 ], "texture": "#texture7", "rotation": 180 } } }, { "name": "cube", "from": [ 3, 4.5, 6 ], "to": [ 4, 6.5, 8 ], "shade": true, "faces": { "north": { "uv": [ 5, 10, 6, 12 ], "texture": "#texture1" }, "east": { "uv": [ 7, 4, 9, 6 ], "texture": "#texture1" }, "south": { "uv": [ 4, 10, 5, 12 ], "texture": "#texture1" }, "west": { "uv": [ 6, 10, 8, 12 ], "texture": "#texture1" }, "up": { "uv": [ 7, 6, 8, 8 ], "texture": "#texture1", "rotation": 180 }, "down": { "uv": [ 8, 6, 9, 8 ], "texture": "#texture1", "rotation": 180 } } }, { "name": "cube", "from": [ 12, 4.5, 6 ], "to": [ 13, 6.5, 8 ], "shade": true, "faces": { "north": { "uv": [ 9, 4, 10, 6 ], "texture": "#texture1" }, "east": { "uv": [ 9, 10, 11, 12 ], "texture": "#texture1" }, "south": { "uv": [ 8, 10, 9, 12 ], "texture": "#texture1" }, "west": { "uv": [ 9, 6, 11, 8 ], "texture": "#texture1" }, "up": { "uv": [ 7, 6, 8, 8 ], "texture": "#texture1", "rotation": 180 }, "down": { "uv": [ 8, 6, 9, 8 ], "texture": "#texture1", "rotation": 180 } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/portable_grid_connected.json ================================================ { "parent": "refinedstorage:block/portable_grid_base", "textures": { "texture1": "refinedstorage:block/portable_grid_2" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/portable_grid_disconnected.json ================================================ { "parent": "refinedstorage:block/portable_grid_base", "textures": { "texture1": "refinedstorage:block/portable_grid_2_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/quartz_enriched_iron_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "refinedstorage:block/quartz_enriched_iron_block" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/storage_monitor.json ================================================ { "parent": "block/cube", "textures": { "particle": "refinedstorage:block/side", "north": "refinedstorage:block/storage_monitor_front", "east": "refinedstorage:block/storage_monitor_left", "south": "refinedstorage:block/storage_monitor_back", "west": "refinedstorage:block/storage_monitor_right", "up": "refinedstorage:block/storage_monitor_top", "down": "refinedstorage:block/bottom" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/wireless_transmitter.json ================================================ { "render_type": "cutout", "parent": "block/cube", "ambientocclusion": false, "textures": { "particle": "refinedstorage:block/wireless_transmitter/wireless_transmitter", "torch": "refinedstorage:block/wireless_transmitter/wireless_transmitter" }, "elements": [ { "from": [ 7, 0, 7 ], "to": [ 9, 10, 9 ], "shade": false, "faces": { "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#torch" }, "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#torch" } } }, { "from": [ 7, 0, 0 ], "to": [ 9, 16, 16 ], "shade": false, "faces": { "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }, "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" } } }, { "from": [ 0, 0, 7 ], "to": [ 16, 16, 9 ], "shade": false, "faces": { "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }, "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" } } }, { "from": [ 7, 0, 7 ], "to": [ 9, 10, 9 ], "shade": false, "faces": { "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } }, { "from": [ 7, 0, 0 ], "to": [ 9, 16, 16 ], "shade": false, "faces": { "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } }, { "from": [ 0, 0, 7 ], "to": [ 16, 16, 9 ], "shade": false, "faces": { "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } }, "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout", "neoforge_data": { "block_light": 15, "sky_light": 15 } } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/block/wireless_transmitter_nonemissive.json ================================================ { "render_type": "cutout", "parent": "block/cube", "ambientocclusion": false, "textures": { "particle": "refinedstorage:block/wireless_transmitter/wireless_transmitter", "torch": "refinedstorage:block/wireless_transmitter/wireless_transmitter" }, "elements": [ { "from": [ 7, 0, 7 ], "to": [ 9, 10, 9 ], "shade": false, "faces": { "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#torch" }, "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#torch" } } }, { "from": [ 7, 0, 0 ], "to": [ 9, 16, 16 ], "shade": false, "faces": { "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }, "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" } } }, { "from": [ 0, 0, 7 ], "to": [ 16, 16, 9 ], "shade": false, "faces": { "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" }, "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#torch" } } }, { "from": [ 7, 0, 7 ], "to": [ 9, 10, 9 ], "shade": false, "faces": { "down": { "uv": [ 7, 13, 9, 15 ], "texture": "#cutout" }, "up": { "uv": [ 7, 6, 9, 8 ], "texture": "#cutout" } } }, { "from": [ 7, 0, 0 ], "to": [ 9, 16, 16 ], "shade": false, "faces": { "west": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout" }, "east": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout" } } }, { "from": [ 0, 0, 7 ], "to": [ 16, 16, 9 ], "shade": false, "faces": { "north": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout" }, "south": { "uv": [ 0, 0, 16, 16 ], "texture": "#cutout" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_block.json ================================================ { "parent": "refinedstorage:block/1024k_fluid_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/1024k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1024k_fluid_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/1024k_fluid_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/16k_storage_block.json ================================================ { "parent": "refinedstorage:block/16k_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/16k_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/16k_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/16k_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/16k_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1k_storage_block.json ================================================ { "parent": "refinedstorage:block/1k_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1k_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/1k_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/1k_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/1k_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_block.json ================================================ { "parent": "refinedstorage:block/256k_fluid_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/256k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/256k_fluid_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/256k_fluid_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_block.json ================================================ { "parent": "refinedstorage:block/4096k_fluid_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/4096k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4096k_fluid_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/4096k_fluid_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4k_storage_block.json ================================================ { "parent": "refinedstorage:block/4k_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4k_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/4k_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/4k_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/4k_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_block.json ================================================ { "parent": "refinedstorage:block/64k_fluid_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/64k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_fluid_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/64k_fluid_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_storage_block.json ================================================ { "parent": "refinedstorage:block/64k_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/64k_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/64k_storage_part.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/64k_storage_part" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/advanced_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/advanced_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/basic_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/basic_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/cable.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/construction_core.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/construction_core" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/constructor.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable", "front": "refinedstorage:block/constructor/constructor", "cutout": "refinedstorage:block/constructor/cutouts/disconnected", "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } }, { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#front", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "east": { "texture": "#border", "uv": [ 14.0, 0.0, 16.0, 16.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 16.0 ] }, "up": { "texture": "#border", "uv": [ 2.0, 0.0, 14.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 2.0, 14.0, 14.0, 16.0 ] } } }, { "name": "Line3", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#cutout", "uv": [ 0.0, 0.0, 16.0, 16.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/crafting_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/crafting_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_fluid_storage_block.json ================================================ { "parent": "refinedstorage:block/creative_fluid_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_fluid_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/creative_fluid_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_portable_grid.json ================================================ { "parent": "refinedstorage:block/portable_grid" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_storage_block.json ================================================ { "parent": "refinedstorage:block/creative_storage_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_storage_disk.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/creative_storage_disk" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_wireless_crafting_monitor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_crafting_monitor_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_crafting_monitor_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_crafting_monitor_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_wireless_fluid_grid.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_fluid_grid_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_fluid_grid_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_fluid_grid_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/creative_wireless_grid.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_grid_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_grid_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_grid_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/destruction_core.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/destruction_core" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/destructor.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable", "front": "refinedstorage:block/destructor/destructor", "cutout": "refinedstorage:block/destructor/cutouts/disconnected", "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } }, { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#front", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "east": { "texture": "#border", "uv": [ 14.0, 0.0, 16.0, 16.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 16.0, 16.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 16.0 ] }, "up": { "texture": "#border", "uv": [ 2.0, 0.0, 14.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 2.0, 14.0, 14.0, 16.0 ] } } }, { "name": "Line3", "from": [ 2.0, 2.0, 0.0 ], "to": [ 14.0, 14.0, 2.0 ], "faces": { "north": { "texture": "#cutout", "uv": [ 0.0, 0.0, 16.0, 16.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/disk_drive.json ================================================ { "parent": "refinedstorage:block/disk_drive" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/exporter.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable", "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } }, { "name": "Line1", "from": [ 6, 6, 0 ], "to": [ 10, 10, 2 ], "faces": { "north": { "uv": [ 0, 0, 4, 4 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 4 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 4, 4 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 4 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 4, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 4, 2 ], "texture": "#border" } } }, { "name": "Line2", "from": [ 5, 5, 2 ], "to": [ 11, 11, 4 ], "faces": { "north": { "uv": [ 0, 0, 6, 6 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 6 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 6, 6 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 6 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 6, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 6, 2 ], "texture": "#border" } } }, { "name": "Line3", "from": [ 3, 3, 4 ], "to": [ 13, 13, 6 ], "faces": { "north": { "uv": [ 0, 0, 10, 10 ], "texture": "#border" }, "east": { "uv": [ 0, 0, 2, 10 ], "texture": "#border" }, "south": { "uv": [ 0, 0, 10, 10 ], "texture": "#border" }, "west": { "uv": [ 0, 0, 2, 10 ], "texture": "#border" }, "up": { "uv": [ 0, 0, 10, 2 ], "texture": "#border" }, "down": { "uv": [ 0, 0, 10, 2 ], "texture": "#border" } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/external_storage.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable", "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } }, { "name": "Line1", "from": [ 7.0, 7.0, 2.0 ], "to": [ 9.0, 9.0, 6.0 ], "faces": { "east": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] } } }, { "name": "Line2", "from": [ 3.0, 3.0, 0.0 ], "to": [ 13.0, 13.0, 2.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/filter.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/filter" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/fluid_interface.json ================================================ { "parent": "refinedstorage:block/fluid_interface_disconnected" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/fortune_1_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/fortune_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/fortune_2_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/fortune_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/fortune_3_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/fortune_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/importer.json ================================================ { "parent": "block/block", "textures": { "cable": "refinedstorage:block/cable", "border": "refinedstorage:block/cable_part_border" }, "elements": [ { "name": "Core", "from": [ 6, 6, 6 ], "to": [ 10, 10, 10 ], "faces": { "north": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "down": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" } } }, { "name": "Part1", "from": [ 10, 6, 6 ], "to": [ 16, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 16, 8, 9 ] }, "faces": { "north": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "down": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" } } }, { "name": "Part2", "from": [ 0, 6, 6 ], "to": [ 6, 10, 10 ], "rotation": { "angle": 0, "axis": "y", "origin": [ 6, 8, 9 ] }, "faces": { "north": { "uv": [ 10, 6, 16, 10 ], "texture": "#cable" }, "east": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "south": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "west": { "uv": [ 6, 6, 10, 10 ], "texture": "#cable" }, "up": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" }, "down": { "uv": [ 0, 6, 6, 10 ], "texture": "#cable" } } }, { "name": "Line1", "from": [ 6.0, 6.0, 4.0 ], "to": [ 10.0, 10.0, 6.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 4.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 4.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 4.0, 2.0 ] } } }, { "name": "Line2", "from": [ 5.0, 5.0, 2.0 ], "to": [ 11.0, 11.0, 4.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 6.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 6.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 6.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 6.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 6.0, 2.0 ] } } }, { "name": "Line3", "from": [ 3.0, 3.0, 0.0 ], "to": [ 13.0, 13.0, 2.0 ], "faces": { "north": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "east": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "south": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 10.0 ] }, "west": { "texture": "#border", "uv": [ 0.0, 0.0, 2.0, 10.0 ] }, "up": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] }, "down": { "texture": "#border", "uv": [ 0.0, 0.0, 10.0, 2.0 ] } } } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/improved_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/improved_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/interface.json ================================================ { "parent": "refinedstorage:block/interface_disconnected" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/machine_casing.json ================================================ { "parent": "refinedstorage:block/machine_casing" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/network_card.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/network_card" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/pattern.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/pattern" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/portable_grid.json ================================================ { "parent": "refinedstorage:block/portable_grid" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/processor_binding.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/processor_binding" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/quartz_enriched_iron.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/quartz_enriched_iron" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/quartz_enriched_iron_block.json ================================================ { "parent": "refinedstorage:block/quartz_enriched_iron_block" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/range_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/range_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/raw_advanced_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/raw_advanced_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/raw_basic_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/raw_basic_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/raw_improved_processor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/raw_improved_processor" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/regulator_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/regulator_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/security_card.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/security_card_inactive" }, "overrides": [ { "predicate": { "refinedstorage:active": 0 }, "model": "refinedstorage:item/security_card_inactive" }, { "predicate": { "refinedstorage:active": 1 }, "model": "refinedstorage:item/security_card_active" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/security_card_active.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/security_card_active" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/security_card_inactive.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/security_card_inactive" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/silicon.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/silicon" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/silk_touch_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/silk_touch_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/speed_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/speed_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/stack_upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/stack_upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/storage_housing.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/storage_housing" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/storage_monitor.json ================================================ { "parent": "refinedstorage:block/storage_monitor" } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/upgrade.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/upgrade" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_crafting_monitor_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_crafting_monitor_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_crafting_monitor_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor_connected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_crafting_monitor_connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_crafting_monitor_disconnected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_crafting_monitor_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_fluid_grid_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_fluid_grid_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_fluid_grid_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid_connected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_fluid_grid_connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_fluid_grid_disconnected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_fluid_grid_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_grid.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_grid_disconnected" }, "overrides": [ { "predicate": { "refinedstorage:connected": 0 }, "model": "refinedstorage:item/wireless_grid_disconnected" }, { "predicate": { "refinedstorage:connected": 1 }, "model": "refinedstorage:item/wireless_grid_connected" } ] } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_grid_connected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_grid_connected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wireless_grid_disconnected.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wireless_grid_disconnected" } } ================================================ FILE: src/main/resources/assets/refinedstorage/models/item/wrench.json ================================================ { "parent": "item/generated", "textures": { "layer0": "refinedstorage:item/wrench" } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/constructor/cutouts/connected.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/black.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/blue.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/brown.png.mcmeta ================================================ { "animation": { "frametime": 1, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/cyan.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/gray.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/green.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/light_blue.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/light_gray.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/lime.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/magenta.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_off.png.mcmeta ================================================ { "animation": { "frametime": 1, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_off_gray.png.mcmeta ================================================ { "animation": { "frametime": 1, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_on.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/nearly_on_gray.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/on.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/orange.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/pink.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/purple.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/red.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/white.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/controller/cutouts/yellow.png.mcmeta ================================================ { "animation": { "frametime": 2, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 ] } } ================================================ FILE: src/main/resources/assets/refinedstorage/textures/block/destructor/cutouts/connected.png.mcmeta ================================================ { "animation": { "frametime": 1, "frames": [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ] } } ================================================ FILE: src/main/resources/data/curios/tags/items/curio.json ================================================ { "replace": false, "values": [ "refinedstorage:wireless_grid", "refinedstorage:creative_wireless_grid", "refinedstorage:wireless_fluid_grid", "refinedstorage:creative_wireless_fluid_grid", "refinedstorage:wireless_crafting_monitor", "refinedstorage:creative_wireless_crafting_monitor" ] } ================================================ FILE: src/main/resources/data/forge/tags/items/silicon.json ================================================ { "replace": false, "values": [ "refinedstorage:silicon" ] } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/autocrafting.json ================================================ { "display": { "icon": { "item": "refinedstorage:crafter" }, "title": { "translate": "advancements.refinedstorage.autocrafting" }, "description": { "translate": "advancements.refinedstorage.autocrafting.description" } }, "parent": "refinedstorage:root", "criteria": { "crafter_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:crafter" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/better_than_a_barrel.json ================================================ { "display": { "icon": { "item": "refinedstorage:storage_monitor" }, "title": { "translate": "advancements.refinedstorage.better_than_a_barrel" }, "description": { "translate": "advancements.refinedstorage.better_than_a_barrel.description" } }, "parent": "refinedstorage:root", "criteria": { "storage_monitor_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:storage_monitor" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/conditional_connecting.json ================================================ { "display": { "icon": { "item": "refinedstorage:relay" }, "title": { "translate": "advancements.refinedstorage.conditional_connecting" }, "description": { "translate": "advancements.refinedstorage.conditional_connecting.description" } }, "parent": "refinedstorage:connecting", "criteria": { "relay_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:relay" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/connecting.json ================================================ { "display": { "icon": { "item": "refinedstorage:cable" }, "title": { "translate": "advancements.refinedstorage.connecting" }, "description": { "translate": "advancements.refinedstorage.connecting.description" } }, "parent": "refinedstorage:root", "criteria": { "cable_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:cable" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/construction.json ================================================ { "display": { "icon": { "item": "refinedstorage:constructor" }, "title": { "translate": "advancements.refinedstorage.construction" }, "description": { "translate": "advancements.refinedstorage.construction.description" } }, "parent": "refinedstorage:exporting", "criteria": { "constructor_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:constructor" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/crafting_on_demand.json ================================================ { "display": { "icon": { "item": "refinedstorage:crafting_upgrade" }, "title": { "translate": "advancements.refinedstorage.crafting_on_demand" }, "description": { "translate": "advancements.refinedstorage.crafting_on_demand.description" } }, "parent": "refinedstorage:pattern_creation", "criteria": { "upgrade_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:crafting_upgrade" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/destruction.json ================================================ { "display": { "icon": { "item": "refinedstorage:destructor" }, "title": { "translate": "advancements.refinedstorage.destruction" }, "description": { "translate": "advancements.refinedstorage.destruction.description" } }, "parent": "refinedstorage:importing", "criteria": { "destructor_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:destructor" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/detecting.json ================================================ { "display": { "icon": { "item": "refinedstorage:detector" }, "title": { "translate": "advancements.refinedstorage.detecting" }, "description": { "translate": "advancements.refinedstorage.detecting.description" } }, "parent": "refinedstorage:root", "criteria": { "detector_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:detector" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/drives.json ================================================ { "display": { "icon": { "item": "refinedstorage:disk_drive" }, "title": { "translate": "advancements.refinedstorage.drives" }, "description": { "translate": "advancements.refinedstorage.drives.description" } }, "parent": "refinedstorage:root", "criteria": { "disk_drive_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:disk_drive" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/exporting.json ================================================ { "display": { "icon": { "item": "refinedstorage:exporter" }, "title": { "translate": "advancements.refinedstorage.exporting" }, "description": { "translate": "advancements.refinedstorage.exporting.description" } }, "parent": "refinedstorage:root", "criteria": { "exporter_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:exporter" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/importing.json ================================================ { "display": { "icon": { "item": "refinedstorage:importer" }, "title": { "translate": "advancements.refinedstorage.importing" }, "description": { "translate": "advancements.refinedstorage.importing.description" } }, "parent": "refinedstorage:root", "criteria": { "importer_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:importer" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/interface_to_the_world.json ================================================ { "display": { "icon": { "item": "refinedstorage:interface" }, "title": { "translate": "advancements.refinedstorage.interface_to_the_world" }, "description": { "translate": "advancements.refinedstorage.interface_to_the_world.description" } }, "parent": "refinedstorage:root", "criteria": { "interface_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:interface" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/managing_patterns.json ================================================ { "display": { "icon": { "item": "refinedstorage:crafter_manager" }, "title": { "translate": "advancements.refinedstorage.managing_patterns" }, "description": { "translate": "advancements.refinedstorage.managing_patterns.description" } }, "parent": "refinedstorage:autocrafting", "criteria": { "crafter_manager_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:crafter_manager" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/manipulating_disks.json ================================================ { "display": { "icon": { "item": "refinedstorage:disk_manipulator" }, "title": { "translate": "advancements.refinedstorage.manipulating_disks" }, "description": { "translate": "advancements.refinedstorage.manipulating_disks.description" } }, "parent": "refinedstorage:drives", "criteria": { "disk_manipulator_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:disk_manipulator" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/monitoring.json ================================================ { "display": { "icon": { "item": "refinedstorage:crafting_monitor" }, "title": { "translate": "advancements.refinedstorage.monitoring" }, "description": { "translate": "advancements.refinedstorage.monitoring.description" } }, "parent": "refinedstorage:autocrafting", "criteria": { "crafting_monitor_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:crafting_monitor" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/no_cables_required.json ================================================ { "display": { "icon": { "item": "refinedstorage:network_transmitter" }, "title": { "translate": "advancements.refinedstorage.no_cables_required" }, "description": { "translate": "advancements.refinedstorage.no_cables_required.description" } }, "parent": "refinedstorage:wireless", "criteria": { "network_transmitter_receiver_card_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:network_transmitter" ] }, { "items": [ "refinedstorage:network_receiver" ] }, { "items": [ "refinedstorage:network_card" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/pattern_creation.json ================================================ { "display": { "icon": { "item": "refinedstorage:pattern" }, "title": { "translate": "advancements.refinedstorage.pattern_creation" }, "description": { "translate": "advancements.refinedstorage.pattern_creation.description" } }, "parent": "refinedstorage:autocrafting", "criteria": { "pattern_and_pattern_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:pattern" ] }, { "items": [ "refinedstorage:pattern_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/portable_storage.json ================================================ { "display": { "icon": { "item": "refinedstorage:portable_grid" }, "title": { "translate": "advancements.refinedstorage.portable_storage" }, "description": { "translate": "advancements.refinedstorage.portable_storage.description" } }, "parent": "refinedstorage:viewing_items", "criteria": { "portable_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:portable_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/root.json ================================================ { "display": { "icon": { "item": "refinedstorage:creative_controller" }, "title": { "translate": "itemGroup.refinedstorage" }, "description": { "translate": "advancements.refinedstorage.controlling.description" }, "background": "refinedstorage:textures/gui/advancements.png" }, "criteria": { "controller_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:controller" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/security.json ================================================ { "display": { "icon": { "item": "refinedstorage:security_manager" }, "title": { "translate": "advancements.refinedstorage.security" }, "description": { "translate": "advancements.refinedstorage.security.description" } }, "parent": "refinedstorage:root", "criteria": { "security_manager_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:security_manager" ] }, { "items": [ "refinedstorage:security_card" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/storing_externally.json ================================================ { "display": { "icon": { "item": "refinedstorage:external_storage" }, "title": { "translate": "advancements.refinedstorage.storing_externally" }, "description": { "translate": "advancements.refinedstorage.storing_externally.description" } }, "parent": "refinedstorage:root", "criteria": { "external_storage_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:external_storage" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/storing_fluids.json ================================================ { "display": { "icon": { "item": "refinedstorage:64k_fluid_storage_disk" }, "title": { "translate": "advancements.refinedstorage.storing_fluids" }, "description": { "translate": "advancements.refinedstorage.storing_fluids.description" } }, "parent": "refinedstorage:drives", "criteria": { "fluid_storage_disk_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:64k_fluid_storage_disk" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/storing_items.json ================================================ { "display": { "icon": { "item": "refinedstorage:1k_storage_disk" }, "title": { "translate": "advancements.refinedstorage.storing_items" }, "description": { "translate": "advancements.refinedstorage.storing_items.description" } }, "parent": "refinedstorage:drives", "criteria": { "storage_disk_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:1k_storage_disk" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/upgrading.json ================================================ { "display": { "icon": { "item": "refinedstorage:upgrade" }, "title": { "translate": "advancements.refinedstorage.upgrading" }, "description": { "translate": "advancements.refinedstorage.upgrading.description" } }, "parent": "refinedstorage:root", "criteria": { "upgrade_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:upgrade" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/upgrading_your_grid.json ================================================ { "display": { "icon": { "item": "refinedstorage:crafting_grid" }, "title": { "translate": "advancements.refinedstorage.upgrading_your_grid" }, "description": { "translate": "advancements.refinedstorage.upgrading_your_grid.description" } }, "parent": "refinedstorage:viewing_items", "criteria": { "crafting_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:crafting_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/viewing_fluids.json ================================================ { "display": { "icon": { "item": "refinedstorage:fluid_grid" }, "title": { "translate": "advancements.refinedstorage.viewing_fluids" }, "description": { "translate": "advancements.refinedstorage.viewing_fluids.description" } }, "parent": "refinedstorage:storing_fluids", "criteria": { "fluid_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:fluid_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/viewing_items.json ================================================ { "display": { "icon": { "item": "refinedstorage:grid" }, "title": { "translate": "advancements.refinedstorage.viewing_items" }, "description": { "translate": "advancements.refinedstorage.viewing_items.description" } }, "parent": "refinedstorage:storing_items", "criteria": { "grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/wireless.json ================================================ { "display": { "icon": { "item": "refinedstorage:wireless_transmitter" }, "title": { "translate": "advancements.refinedstorage.wireless" }, "description": { "translate": "advancements.refinedstorage.wireless.description" } }, "parent": "refinedstorage:root", "criteria": { "wireless_transmitter_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:wireless_transmitter" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/wireless_fluids.json ================================================ { "display": { "icon": { "item": "refinedstorage:wireless_fluid_grid" }, "title": { "translate": "advancements.refinedstorage.wireless_fluids" }, "description": { "translate": "advancements.refinedstorage.wireless_fluids.description" } }, "parent": "refinedstorage:wireless", "criteria": { "wireless_fluid_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:wireless_fluid_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/wireless_items.json ================================================ { "display": { "icon": { "item": "refinedstorage:wireless_grid" }, "title": { "translate": "advancements.refinedstorage.wireless_items" }, "description": { "translate": "advancements.refinedstorage.wireless_items.description" } }, "parent": "refinedstorage:wireless", "criteria": { "wireless_grid_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:wireless_grid" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/advancements/wireless_monitoring.json ================================================ { "display": { "icon": { "item": "refinedstorage:wireless_crafting_monitor" }, "title": { "translate": "advancements.refinedstorage.wireless_monitoring" }, "description": { "translate": "advancements.refinedstorage.wireless_monitoring.description" } }, "parent": "refinedstorage:wireless", "criteria": { "wireless_crafting_monitor_in_inventory": { "trigger": "minecraft:inventory_changed", "conditions": { "items": [ { "items": [ "refinedstorage:wireless_crafting_monitor" ] } ] } } } } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/1024k_fluid_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:1024k_fluid_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/16k_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:16k_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/1k_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:1k_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/256k_fluid_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:256k_fluid_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/4096k_fluid_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:4096k_fluid_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/4k_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:4k_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/64k_fluid_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:64k_fluid_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/64k_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:64k_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/cable.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:cable" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/constructor.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:constructor" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/creative_fluid_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:creative_fluid_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/creative_portable_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:creative_portable_grid", "functions": [ { "function": "refinedstorage:portable_grid" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/creative_storage_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:creative_storage_block", "functions": [ { "function": "refinedstorage:storage_block" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/destructor.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:destructor" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/disk_drive.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:disk_drive" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/exporter.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:exporter" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/external_storage.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:external_storage" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/fluid_interface.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:fluid_interface" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/importer.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:importer" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/interface.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:interface" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/machine_casing.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:machine_casing" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/portable_grid.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:portable_grid", "functions": [ { "function": "refinedstorage:portable_grid" } ] } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/quartz_enriched_iron_block.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:quartz_enriched_iron_block" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/loot_tables/blocks/storage_monitor.json ================================================ { "type": "minecraft:block", "pools": [ { "rolls": 1, "entries": [ { "type": "minecraft:item", "name": "refinedstorage:storage_monitor" } ], "conditions": [ { "condition": "minecraft:survives_explosion" } ] } ] } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:1024k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:1024k_fluid_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:1024k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:1024k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:1024k_fluid_storage_part" } ], "result": { "item": "refinedstorage:1024k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1024k_fluid_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:improved_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:256k_fluid_storage_part" }, "R": { "item": "minecraft:bucket" } }, "result": { "item": "refinedstorage:1024k_fluid_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/16k_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:16k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:16k_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/16k_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:16k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:16k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/16k_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:16k_storage_part" } ], "result": { "item": "refinedstorage:16k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/16k_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:improved_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:4k_storage_part" }, "R": { "item": "minecraft:redstone" } }, "result": { "item": "refinedstorage:16k_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1k_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:1k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:1k_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1k_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:1k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:1k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1k_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:1k_storage_part" } ], "result": { "item": "refinedstorage:1k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/1k_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "SES", "GRG", "SGS" ], "key": { "S": { "tag": "forge:silicon" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" } }, "result": { "item": "refinedstorage:1k_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:256k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:256k_fluid_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:256k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:256k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:256k_fluid_storage_part" } ], "result": { "item": "refinedstorage:256k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/256k_fluid_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:basic_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:64k_fluid_storage_part" }, "R": { "item": "minecraft:bucket" } }, "result": { "item": "refinedstorage:256k_fluid_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:4096k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:4096k_fluid_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:4096k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:4096k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:4096k_fluid_storage_part" } ], "result": { "item": "refinedstorage:4096k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4096k_fluid_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:advanced_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:1024k_fluid_storage_part" }, "R": { "item": "minecraft:bucket" } }, "result": { "item": "refinedstorage:4096k_fluid_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4k_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:4k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:4k_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4k_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:4k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:4k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4k_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:4k_storage_part" } ], "result": { "item": "refinedstorage:4k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/4k_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:basic_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:1k_storage_part" }, "R": { "item": "minecraft:redstone" } }, "result": { "item": "refinedstorage:4k_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:64k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:64k_fluid_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:64k_fluid_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:64k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:64k_fluid_storage_part" } ], "result": { "item": "refinedstorage:64k_fluid_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_fluid_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "SES", "GRG", "SGS" ], "key": { "S": { "tag": "forge:silicon" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:bucket" } }, "result": { "item": "refinedstorage:64k_fluid_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_storage_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "ERE" ], "key": { "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:64k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:64k_storage_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_storage_disk.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RPR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "P": { "item": "refinedstorage:64k_storage_part" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:64k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_storage_disk_from_storage_housing.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:storage_housing" }, { "item": "refinedstorage:64k_storage_part" } ], "result": { "item": "refinedstorage:64k_storage_disk" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/64k_storage_part.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PEP", "SRS", "PSP" ], "key": { "P": { "item": "refinedstorage:advanced_processor" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:16k_storage_part" }, "R": { "item": "minecraft:redstone" } }, "result": { "item": "refinedstorage:64k_storage_part" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/advanced_processor.json ================================================ { "type": "minecraft:smelting", "ingredient": { "item": "refinedstorage:raw_advanced_processor" }, "result": "refinedstorage:advanced_processor", "experience": 0.5 } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/basic_processor.json ================================================ { "type": "minecraft:smelting", "ingredient": { "item": "refinedstorage:raw_basic_processor" }, "result": "refinedstorage:basic_processor", "experience": 0.5 } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/block_of_quartz_enriched_iron.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "EEE", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:quartz_enriched_iron_block" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/cable.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "GRG", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" } }, "result": { "item": "refinedstorage:cable", "count": 12 } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/construction_core.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:basic_processor" }, { "item": "minecraft:glowstone_dust" } ], "result": { "item": "refinedstorage:construction_core" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/constructor.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ECE", "RMR", "EIE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "item": "refinedstorage:construction_core" }, "R": { "item": "minecraft:redstone" }, "M": { "item": "refinedstorage:cable" }, "I": { "item": "refinedstorage:improved_processor" } }, "result": { "item": "refinedstorage:constructor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/controller.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "SMS", "ESE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "item": "refinedstorage:advanced_processor" }, "S": { "tag": "forge:silicon" }, "M": { "item": "refinedstorage:machine_casing" } }, "result": { "item": "refinedstorage:controller" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/cover.json ================================================ { "type": "refinedstorage:cover_recipe" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/crafter.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ECE", "AMA", "EDE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "item": "refinedstorage:construction_core" }, "A": { "item": "refinedstorage:advanced_processor" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" } }, "result": { "item": "refinedstorage:crafter" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/crafter_manager.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PCG", "EMG", "PCG" ], "key": { "P": { "item": "refinedstorage:advanced_processor" }, "C": { "tag": "refinedstorage:crafter" }, "G": { "tag": "forge:glass" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "M": { "item": "refinedstorage:machine_casing" } }, "result": { "item": "refinedstorage:crafter_manager" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/crafting_monitor.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PAG", "EMG", "PAG" ], "key": { "P": { "item": "refinedstorage:improved_processor" }, "A": { "item": "refinedstorage:pattern" }, "G": { "tag": "forge:glass" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "M": { "item": "refinedstorage:machine_casing" } }, "result": { "item": "refinedstorage:crafting_monitor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/crafting_upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EOE", "CUC", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "tag": "refinedstorage:crafting_tables" }, "O": { "item": "refinedstorage:construction_core" }, "U": { "item": "refinedstorage:upgrade" } }, "result": { "item": "refinedstorage:crafting_upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/destruction_core.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:basic_processor" }, { "item": "minecraft:quartz" } ], "result": { "item": "refinedstorage:destruction_core" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/destructor.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EDE", "RMR", "EIE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "D": { "item": "refinedstorage:destruction_core" }, "R": { "item": "minecraft:redstone" }, "M": { "item": "refinedstorage:cable" }, "I": { "item": "refinedstorage:improved_processor" } }, "result": { "item": "refinedstorage:destructor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/detector.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ERE", "CMC", "EPE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "item": "minecraft:comparator" }, "R": { "item": "minecraft:redstone_torch" }, "M": { "item": "refinedstorage:machine_casing" }, "P": { "item": "refinedstorage:improved_processor" } }, "result": { "item": "refinedstorage:detector" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/disk_drive.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ECE", "EME", "EPE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "tag": "forge:chests" }, "M": { "item": "refinedstorage:machine_casing" }, "P": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:disk_drive" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/disk_manipulator.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ESE", "CMD", "ESE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "refinedstorage:storage_housing" }, "C": { "item": "refinedstorage:construction_core" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" } }, "result": { "item": "refinedstorage:disk_manipulator" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/exporter.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:cable" }, { "item": "refinedstorage:construction_core" }, { "item": "refinedstorage:improved_processor" } ], "result": { "item": "refinedstorage:exporter" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/external_storage.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "CED", "HMH", "EPE" ], "key": { "C": { "item": "refinedstorage:construction_core" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "D": { "item": "refinedstorage:destruction_core" }, "H": { "tag": "forge:chests" }, "M": { "item": "refinedstorage:cable" }, "P": { "item": "refinedstorage:improved_processor" } }, "result": { "item": "refinedstorage:external_storage" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/filter.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "PHP", "EPE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "item": "minecraft:paper" }, "H": { "item": "minecraft:hopper" } }, "result": { "item": "refinedstorage:filter" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/fluid_interface.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:interface" }, { "item": "refinedstorage:advanced_processor" }, { "item": "minecraft:bucket" } ], "result": { "item": "refinedstorage:fluid_interface" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/fortune_1_upgrade.json ================================================ { "type": "refinedstorage:upgrade_with_enchanted_book", "enchantment": "minecraft:fortune", "level": 1, "result": "refinedstorage:fortune_1_upgrade" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/fortune_2_upgrade.json ================================================ { "type": "refinedstorage:upgrade_with_enchanted_book", "enchantment": "minecraft:fortune", "level": 2, "result": "refinedstorage:fortune_2_upgrade" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/fortune_3_upgrade.json ================================================ { "type": "refinedstorage:upgrade_with_enchanted_book", "enchantment": "minecraft:fortune", "level": 3, "result": "refinedstorage:fortune_3_upgrade" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/grid.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PCG", "EMG", "PDG" ], "key": { "P": { "item": "refinedstorage:improved_processor" }, "C": { "item": "refinedstorage:construction_core" }, "G": { "tag": "forge:glass" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" } }, "result": { "item": "refinedstorage:grid" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/hollow_cover.json ================================================ { "type": "refinedstorage:hollow_cover_recipe" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/importer.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:cable" }, { "item": "refinedstorage:destruction_core" }, { "item": "refinedstorage:improved_processor" } ], "result": { "item": "refinedstorage:importer" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/improved_processor.json ================================================ { "type": "minecraft:smelting", "ingredient": { "item": "refinedstorage:raw_improved_processor" }, "result": "refinedstorage:improved_processor", "experience": 0.5 } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/interface.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "UIU", "RMR", "UEU" ], "key": { "I": { "item": "refinedstorage:importer" }, "E": { "item": "refinedstorage:exporter" }, "M": { "item": "refinedstorage:machine_casing" }, "R": { "item": "minecraft:redstone" }, "U": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:interface" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/machine_casing.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "ESE", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "tag": "forge:stone" } }, "result": { "item": "refinedstorage:machine_casing" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/network_card.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "PAP", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "item": "minecraft:paper" }, "A": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:network_card" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/network_receiver.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ANA", "CMD", "EEE" ], "key": { "E": { "tag": "forge:ender_pearls" }, "C": { "item": "refinedstorage:construction_core" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" }, "A": { "item": "refinedstorage:advanced_processor" }, "N": { "item": "minecraft:netherite_ingot" } }, "result": { "item": "refinedstorage:network_receiver" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/network_transmitter.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "CMD", "ANA" ], "key": { "E": { "tag": "forge:ender_pearls" }, "C": { "item": "refinedstorage:construction_core" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" }, "A": { "item": "refinedstorage:advanced_processor" }, "N": { "item": "minecraft:netherite_ingot" } }, "result": { "item": "refinedstorage:network_transmitter" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/pattern.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "RGR", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:pattern" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/portable_grid.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EGE", "ECE", "EFE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "G": { "tag": "refinedstorage:grid" }, "F": { "item": "refinedstorage:fluid_grid" }, "C": { "tag": "refinedstorage:controller" } }, "result": { "item": "refinedstorage:portable_grid" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/processor_binding.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ " ", "SLS", " " ], "key": { "S": { "tag": "forge:string" }, "L": { "tag": "forge:slimeballs" } }, "result": { "item": "refinedstorage:processor_binding", "count": 8 } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/quartz_enriched_iron.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "II", "IQ" ], "key": { "I": { "item": "minecraft:iron_ingot" }, "Q": { "item": "minecraft:quartz" } }, "result": { "item": "refinedstorage:quartz_enriched_iron", "count": 4 } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/quartz_enriched_iron_from_block.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:quartz_enriched_iron_block" } ], "result": { "item": "refinedstorage:quartz_enriched_iron", "count": 9 } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/range_upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "PUP", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "tag": "forge:ender_pearls" }, "U": { "item": "refinedstorage:upgrade" } }, "result": { "item": "refinedstorage:range_upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/raw_advanced_processor.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:processor_binding" }, { "item": "minecraft:diamond" }, { "tag": "forge:silicon" }, { "item": "minecraft:redstone" } ], "result": { "item": "refinedstorage:raw_advanced_processor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/raw_basic_processor.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:processor_binding" }, { "item": "minecraft:iron_ingot" }, { "tag": "forge:silicon" }, { "item": "minecraft:redstone" } ], "result": { "item": "refinedstorage:raw_basic_processor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/raw_improved_processor.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:processor_binding" }, { "item": "minecraft:gold_ingot" }, { "tag": "forge:silicon" }, { "item": "minecraft:redstone" } ], "result": { "item": "refinedstorage:raw_improved_processor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/regulator_upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ECE", "RUR", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "R": { "item": "minecraft:redstone" }, "C": { "item": "minecraft:comparator" }, "U": { "item": "refinedstorage:upgrade" } }, "result": { "item": "refinedstorage:regulator_upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/relay.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "refinedstorage:machine_casing" }, { "item": "refinedstorage:cable" }, { "item": "minecraft:redstone_torch" } ], "result": { "item": "refinedstorage:relay" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/security_card.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EEE", "CAC", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "item": "refinedstorage:network_card" }, "A": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:security_card" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/security_manager.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ECE", "SMS", "ESE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "C": { "tag": "forge:chests" }, "S": { "item": "refinedstorage:security_card" }, "M": { "item": "refinedstorage:machine_casing" } }, "result": { "item": "refinedstorage:security_manager" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/silicon.json ================================================ { "type": "minecraft:smelting", "ingredient": { "item": "minecraft:quartz" }, "result": "refinedstorage:silicon", "experience": 0.5 } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/silk_touch_upgrade.json ================================================ { "type": "refinedstorage:upgrade_with_enchanted_book", "enchantment": "minecraft:silk_touch", "result": "refinedstorage:silk_touch_upgrade" } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/speed_upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "ESE", "SUS", "EEE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "S": { "item": "minecraft:sugar" }, "U": { "item": "refinedstorage:upgrade" } }, "result": { "item": "refinedstorage:speed_upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/stack_upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "USU", "SUS", "USU" ], "key": { "U": { "item": "minecraft:sugar" }, "S": { "item": "refinedstorage:speed_upgrade" } }, "result": { "item": "refinedstorage:stack_upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/storage_housing.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GRG", "R R", "EEE" ], "key": { "G": { "tag": "forge:glass" }, "R": { "item": "minecraft:redstone" }, "E": { "item": "refinedstorage:quartz_enriched_iron" } }, "result": { "item": "refinedstorage:storage_housing" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/storage_monitor.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "PCG", "EMG", "PDG" ], "key": { "P": { "item": "refinedstorage:basic_processor" }, "C": { "item": "refinedstorage:construction_core" }, "G": { "tag": "forge:glass" }, "E": { "item": "refinedstorage:quartz_enriched_iron" }, "M": { "item": "refinedstorage:machine_casing" }, "D": { "item": "refinedstorage:destruction_core" } }, "result": { "item": "refinedstorage:storage_monitor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/upgrade.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EGE", "EPE", "EGE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "G": { "tag": "forge:glass" }, "P": { "item": "refinedstorage:improved_processor" } }, "result": { "item": "refinedstorage:upgrade" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/wireless_crafting_monitor.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "EAE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "tag": "forge:ender_pearls" }, "M": { "tag": "refinedstorage:crafting_monitor" }, "A": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:wireless_crafting_monitor" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/wireless_fluid_grid.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EGE", "EAE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "tag": "forge:ender_pearls" }, "G": { "tag": "refinedstorage:fluid_grid" }, "A": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:wireless_fluid_grid" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/wireless_grid.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EGE", "EAE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "tag": "forge:ender_pearls" }, "G": { "tag": "refinedstorage:grid" }, "A": { "item": "refinedstorage:advanced_processor" } }, "result": { "item": "refinedstorage:wireless_grid" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/wireless_transmitter.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EME", "EAE" ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "A": { "item": "refinedstorage:advanced_processor" }, "M": { "item": "refinedstorage:machine_casing" }, "P": { "tag": "forge:ender_pearls" } }, "result": { "item": "refinedstorage:wireless_transmitter" } } ================================================ FILE: src/main/resources/data/refinedstorage/recipes/wrench.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "EPE", "EEE", " E " ], "key": { "E": { "item": "refinedstorage:quartz_enriched_iron" }, "P": { "item": "refinedstorage:basic_processor" } }, "result": { "item": "refinedstorage:wrench" } } ================================================ FILE: src/main/resources/data/refinedstorage/tags/items/crafting_tables.json ================================================ { "replace": false, "values": [ "minecraft:crafting_table" ] } ================================================ FILE: src/main/resources/pack.mcmeta ================================================ { "pack": { "description": { "text": "Refined Storage resources" }, "pack_format": 18 } } ================================================ FILE: tools/missing-translation-keys.sh ================================================ # usage: missing-translation-keys.sh nl_nl if [ $# -ne 1 ]; then echo "missing language to compare with" exit fi filename=src/main/resources/assets/refinedstorage/lang/$1.lang if [ ! -f $filename ]; then echo "$filename not found" exit fi BASE_LANG="en_us" cat src/main/resources/assets/refinedstorage/lang/$BASE_LANG.lang | cut -d "=" -f 1 > a.lang cat $filename | cut -d "=" -f 1 > b.lang diff -s -y a.lang b.lang rm a.lang b.lang